package com.ctshk.rpc.order.tour.service.impl;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.TreeMap;

import com.ctshk.common.enums.NumberConstant;
import com.ctshk.common.enums.StrConstant;
import com.ctshk.common.enums.TouristType;
import com.ctshk.common.utils.*;
import com.ctshk.rpc.order.tour.code.*;
import com.ctshk.rpc.order.tour.dto.*;
import com.ctshk.rpc.order.tour.dto.custom.*;
import com.ctshk.rpc.order.tour.req.*;
import com.ctshk.rpc.order.tour.req.custom.CustomOrderIdReq;
import com.ctshk.rpc.order.tour.service.ISeriesOrderTouristFeeAdjustService;
import com.ctshk.rpc.order.tour.vo.ExcelData;
import com.ctshk.rpc.order.tour.vo.ExcelTemp;
import com.ctshk.rpc.order.tour.vo.TouristCollectionFeeJson;
import com.ctshk.rpc.system.dto.*;
import com.ctshk.rpc.tour.dto.schedule.*;
import com.ctshk.rpc.tour.req.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.service.support.BaseService;
import com.ctshk.rpc.order.tour.entity.SeriesOrder;
import com.ctshk.rpc.order.tour.entity.SeriesOrderAmountStatistics;
import com.ctshk.rpc.order.tour.entity.SeriesOrderCollection;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristFeeAdjust;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristGroup;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristInfo;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristOtherFee;
import com.ctshk.rpc.order.tour.entity.SeriesOrderTouristRoom;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderAmountStatisticsMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderCollectionMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristFeeAdjustMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristGroupMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristInfoMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristOtherFeeMapper;
import com.ctshk.rpc.order.tour.mapper.SeriesOrderTouristRoomMapper;
import com.ctshk.rpc.order.tour.service.ISeriesOrderService;
import com.ctshk.rpc.order.tour.service.ISeriesOrderTouristInfoService;
import com.ctshk.rpc.order.tour.service.ISeriesOrderTouristOtherFeeService;
import com.ctshk.rpc.order.tour.util.Utils;
import com.ctshk.rpc.order.tour.vo.AreaPhone;
import com.ctshk.rpc.system.req.AreaQueryLikeNameReq;
import com.ctshk.rpc.system.req.MainDataRowFieldDataReq;
import com.ctshk.rpc.system.req.MainDataTouristTypeListReq;
import com.ctshk.rpc.system.service.IMainDataTableService;
import com.ctshk.rpc.system.service.IMainDataTouristTypeService;
import com.ctshk.rpc.system.service.ISysAreaService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.tour.service.ISeriesTripScheduleService;

/**
 * <p>
 * 系列团游客信息 服务实现类
 * </p>
 *
 * @author 谭响
 * @since 2021-01-18
 */
@DubboService
public class SeriesOrderTouristInfoServiceImpl extends ServiceImpl<SeriesOrderTouristInfoMapper, SeriesOrderTouristInfo> implements ISeriesOrderTouristInfoService, BaseService {

    @Autowired
    private SeriesOrderTouristInfoMapper seriesOrderTouristInfoMapper;
    @Autowired
    private SeriesOrderTouristRoomMapper seriesOrderTouristRoomMapper;
    @Autowired
    private SeriesOrderAmountStatisticsMapper seriesOrderAmountStatisticsMapper;
    @Autowired
    private SeriesOrderTouristOtherFeeMapper seriesOrderTouristOtherFeeMapper;
    @Autowired
    private SeriesOrderTouristFeeAdjustMapper seriesOrderTouristFeeAdjustMapper;

    @DubboReference
    private ISeriesTripScheduleService iSeriesTripScheduleService;
    @Autowired
    private ISeriesOrderTouristFeeAdjustService iSeriesOrderTouristFeeAdjustService;
    @Autowired
    private ISeriesOrderTouristInfoService iSeriesOrderTouristInfoService;

    @Autowired
    private ISeriesOrderTouristOtherFeeService iSeriesOrderTouristOtherFeeService;

    @Autowired
    private SeriesOrderMapper seriesOrderMapper;
    @Autowired
    private SeriesOrderTouristGroupMapper seriesOrderTouristGroupMapper;


    @DubboReference
    private ISysUserService iSysUserService;

    @DubboReference
    private IMainDataTouristTypeService iMainDataTouristTypeService;

    @DubboReference
    private ISysAreaService iSysAreaService;

    @Autowired
    private SeriesOrderCollectionMapper seriesOrderCollectionMapper;

    @DubboReference
    private IMainDataTableService iMainDataTableService;

    @Autowired
    private ISeriesOrderService iSeriesOrderService;
    
//    
//    ISeriesOrderTouristOtherFeeService seriesOrderTouristOtherFeeService;


    /**
     * 插入批量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertBatch(SeriesOrderTouristInfoInsertBatchReq req) {
        List<SeriesOrderTouristInfo> seriesOrderTouristInfoList = new ArrayList<>();
        for(int i = 0; i < req.getPeople(); i++) {
            SeriesOrderTouristInfo seriesOrderTouristInfo = new SeriesOrderTouristInfo();
            seriesOrderTouristInfo.setOrderId(req.getOrderId());
            seriesOrderTouristInfo.setScheduleId(req.getScheduleId());
            seriesOrderTouristInfo.setMainDataId(req.getMainDataId());
            seriesOrderTouristInfo.setPayStatus(PayStatusCode.WAIT.getCode());
            seriesOrderTouristInfo.setNoshow(LockStatusCode.NO.getCode());
            seriesOrderTouristInfo.setLockStatus(LockStatusCode.NO.getCode());
            seriesOrderTouristInfo.setIsDeleted(IsDeletedCode.NO.getCode());
            LocalDateTime now = LocalDateTime.now();
            seriesOrderTouristInfo.setGmtCreate(now);
            seriesOrderTouristInfo.setGmtModified(now);
            seriesOrderTouristInfo.setCreateId(req.getUserId());
            seriesOrderTouristInfo.setModifiedId(req.getUserId());
            seriesOrderTouristInfo.setGroupFee(req.getGroupFee());
            seriesOrderTouristInfoList.add(seriesOrderTouristInfo);
        }
        super.saveBatch(seriesOrderTouristInfoList);
    }

    /**
     * 插入批量
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveBatch(List<SeriesOrderTouristInfoSaveBatchReq> listReq) {
        List<SeriesOrderTouristInfo> touristInfoList = new ArrayList<>();
        for (SeriesOrderTouristInfoSaveBatchReq saveBatchReq : listReq) {
            SeriesOrderTouristInfo touristInfo = EntityUtil.copy(saveBatchReq, SeriesOrderTouristInfo.class);
            if(saveBatchReq.getCertificateList() != null) {
                int size = saveBatchReq.getCertificateList().size();
                if (size >= 1) {
                    SeriesOrderTouristInfoSaveBatchCertificateReq certificateReq = saveBatchReq.getCertificateList().get(0);
                    touristInfo.setCertificateType1(certificateReq.getCertificateType());
                    touristInfo.setCertificateTypeId1(certificateReq.getCertificateTypeId());
                    touristInfo.setCertificateNumber1(certificateReq.getCertificateNumber());
                    touristInfo.setCertificateValidDate1(certificateReq.getCertificateValidDate());
                    touristInfo.setCertificatePlace1(certificateReq.getCertificatePlace());
                    touristInfo.setCertificatePlaceId1(certificateReq.getCertificatePlaceId());
                }
                if (size >= 2) {
                    SeriesOrderTouristInfoSaveBatchCertificateReq certificateReq = saveBatchReq.getCertificateList().get(1);
                    touristInfo.setCertificateType2(certificateReq.getCertificateType());
                    touristInfo.setCertificateTypeId2(certificateReq.getCertificateTypeId());
                    touristInfo.setCertificateNumber2(certificateReq.getCertificateNumber());
                    touristInfo.setCertificateValidDate2(certificateReq.getCertificateValidDate());
                    touristInfo.setCertificatePlace2(certificateReq.getCertificatePlace());
                    touristInfo.setCertificatePlaceId2(certificateReq.getCertificatePlaceId());
                }
                if (size >= 3) {
                    SeriesOrderTouristInfoSaveBatchCertificateReq certificateReq = saveBatchReq.getCertificateList().get(2);
                    touristInfo.setCertificateType3(certificateReq.getCertificateType());
                    touristInfo.setCertificateTypeId3(certificateReq.getCertificateTypeId());
                    touristInfo.setCertificateNumber3(certificateReq.getCertificateNumber());
                    touristInfo.setCertificateValidDate3(certificateReq.getCertificateValidDate());
                    touristInfo.setCertificatePlace3(certificateReq.getCertificatePlace());
                    touristInfo.setCertificatePlaceId3(certificateReq.getCertificatePlaceId());
                }
            }
            touristInfoList.add(touristInfo);
        }
        return super.saveBatch(touristInfoList);
    }

    /**
     * 编辑
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result edit(SeriesOrderTouristInfoEditReq req) {

        int age = req.getBirthday().until(LocalDate.now()).getYears();

        //获取团期，判断是否能下单
        SeriesTripScheduleDTO tripScheduleDTO = iSeriesTripScheduleService.getTripScheduleId(req.getScheduleId());

        QueryWrapper<SeriesOrderTouristInfo> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getOrderId, req.getOrderId());
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getId, req.getId());
        queryWrapper2.lambda().eq(SeriesOrderTouristInfo::getIsDeleted, IsDeletedCode.NO.getCode());
        SeriesOrderTouristInfo touristInfo = seriesOrderTouristInfoMapper.selectOne(queryWrapper2);
        if (touristInfo == null) {
            return Result.failed(SystemError.SYS_411);
        }

        //是否锁定
        if (Objects.equals(touristInfo.getLockStatus(),1)){
            return Result.failed(SystemError.TOUR_ORDER_30025);
        }

        //判断年龄
        List<Passenger> passengers = tripScheduleDTO.getSeriesTripScheduleTeamRuleDTO().getPassenger();
        for (Passenger passenger : passengers){
            if (Objects.equals(passenger.getMainDataId(),touristInfo.getMainDataId())){
                if (age >= passenger.getAgeBegin() && age < passenger.getAgeEnd()){
                    break;
                }else{
                    throw new BusinessException(SystemError.CUSTOM_ORDER_4004);
                }
            }
        }

        //订单统计
        QueryWrapper<SeriesOrderAmountStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeriesOrderAmountStatistics::getOrderId, req.getOrderId());
        SeriesOrderAmountStatistics statistics = seriesOrderAmountStatisticsMapper.selectOne(queryWrapper);

        //团费
        BigDecimal orderGroupFee = statistics.getTotalTourFee();
        //应收
        BigDecimal orderTotalReceivables = statistics.getTotalReceivables();
        //实收
        BigDecimal orderTotalPaidIn = statistics.getTotalPaidIn();
        //已退款
        BigDecimal orderRefundAmount = statistics.getRefundAmount();
        //代收费用
        BigDecimal orderCollectionFee = statistics.getCollectionFee();
        //调整费用
        BigDecimal orderAdjustmentCost = statistics.getAdjustmentCost();
        //其他金额
        BigDecimal orderOtherAmount = statistics.getOtherAmount();
        //已出单据金额
        BigDecimal orderReceiptedAmount = statistics.getReceiptedAmount();
        //未收
        BigDecimal orderRemainingReceivables = statistics.getRemainingReceivables();

        //团费
        BigDecimal groupFee = touristInfo.getGroupFee();
        //应收
        BigDecimal totalReceivables = touristInfo.getTotalReceivables();
        //实收
        BigDecimal totalPaidIn = touristInfo.getTotalPaidIn();
        //已退款
        BigDecimal refundAmount = touristInfo.getRefundAmount();
        //代收费用
        BigDecimal collectionFee = BigDecimal.ZERO;
        //调整费用
        BigDecimal adjustmentCost = touristInfo.getAdjustmentCost();
        //其他金额
        BigDecimal otherAmount = touristInfo.getOtherAmount();
        //已出单据金额
        BigDecimal receiptedAmount = touristInfo.getReceiptedAmount();
        //未收
        BigDecimal remainingReceivables = touristInfo.getRemainingReceivables();

        LocalDateTime now = LocalDateTime.now();
        SeriesOrderTouristInfo updateObject = EntityUtil.copy(req, SeriesOrderTouristInfo.class);

        List<SeriesOrderTouristOtherFeeSaveBatchReq> otherFeeSaveBatchReqList = new ArrayList<>();
        List<TouristCollectionFeeJson> collectionFeeJsonList = new ArrayList<>();

        if(Objects.equals(tripScheduleDTO.getCostSharingType(), CostSharingType.DEFAULT.getCode())) {
            //默认模板
            TripScheduleDefaultCostDTO tripScheduleDefaultCostDTO = tripScheduleDTO.getTripScheduleDefaultCost();
            List<SeriesTripScheduleDefaultCostCollectionDTO> costCollectionList = tripScheduleDefaultCostDTO.getCostCollectionList();

            if (CollectionUtils.isNotEmpty(costCollectionList)){
                for (SeriesTripScheduleDefaultCostCollectionDTO seriesTripScheduleDefaultCostCollectionDTO : costCollectionList) {
                    SeriesTripScheduleDefaultCostTouristTypeDTO selectTypeDTO = null;

                    //判断代收费用中是否有符合年龄范围的代收费用
                    for (SeriesTripScheduleDefaultCostTouristTypeDTO typeDTO : seriesTripScheduleDefaultCostCollectionDTO.getCostCollectionTypeList()) {
                        if (age >= typeDTO.getAgeBegin() && age <= typeDTO.getAgeEnd()) {
                            selectTypeDTO = typeDTO;
                            break;
                        }
                    }

                    if (selectTypeDTO == null) {
                        continue;
                    }

                    TouristCollectionFeeJson collectionFeeJson = new TouristCollectionFeeJson();
                    collectionFeeJson.setProjectName(seriesTripScheduleDefaultCostCollectionDTO.getProjectName());
                    collectionFeeJson.setMainDataId(seriesTripScheduleDefaultCostCollectionDTO.getMainDataId());
                    collectionFeeJson.setAdjustType(1);
                    collectionFeeJson.setTotalAmount(selectTypeDTO.getTotalAmount().multiply(new BigDecimal(seriesTripScheduleDefaultCostCollectionDTO.getExchangeRate())).setScale(2,BigDecimal.ROUND_HALF_UP));
                    collectionFeeJsonList.add(collectionFeeJson);

                    //累计代收费用
                    collectionFee = collectionFee.add(selectTypeDTO.getTotalAmount());
                    //应收=团费+代收+调整+其他
                    totalReceivables = ((groupFee.add(collectionFee)).add(adjustmentCost)).add(otherAmount);
                    //未收=应收-实收
                    remainingReceivables = totalReceivables.subtract(totalPaidIn);
                }
                if (collectionFeeJsonList.size() > 0) {
                    touristInfo.setCollectionFeeJson(JSON.toJSONString(collectionFeeJsonList));
                }
            }


            //代收费用
            orderCollectionFee = orderCollectionFee.add(collectionFee);
            //应收=团费+代收+调整+其他
            orderTotalReceivables = ((orderGroupFee.add(orderCollectionFee)).add(orderAdjustmentCost)).add(orderOtherAmount);
            //未收=应收-实收
            orderRemainingReceivables = orderTotalReceivables.subtract(orderTotalPaidIn);

        }else if(Objects.equals(tripScheduleDTO.getCostSharingType(), CostSharingType.CUSTOM.getCode())) {
            //自定义
            TripCustomCostReq tripCustomCostReq = tripScheduleDTO.getTripCustomCostReq();
            List<SeriesTripDefaultCostCollectionReq> customCostCollectionList =  tripCustomCostReq.getCostCollectionList();
            if (CollectionUtils.isNotEmpty(customCostCollectionList)){
                for (SeriesTripDefaultCostCollectionReq seriesTripDefaultCostCollectionReq : customCostCollectionList) {
                    SeriesTripDefaultCostCollectionTypeReq selectTypeDTO = null;

                    //判断代收费用中是否有符合年龄范围的代收费用
                    for (SeriesTripDefaultCostCollectionTypeReq typeDTO : seriesTripDefaultCostCollectionReq.getCostCollectionTypeList()) {
                        if (age >= typeDTO.getAgeBegin() && age <= typeDTO.getAgeEnd()) {
                            selectTypeDTO = typeDTO;
                            break;
                        }
                    }

                    if (selectTypeDTO == null) {
                        continue;
                    }

                    TouristCollectionFeeJson collectionFeeJson = new TouristCollectionFeeJson();
                    collectionFeeJson.setProjectName(seriesTripDefaultCostCollectionReq.getProjectName());
                    collectionFeeJson.setMainDataId(seriesTripDefaultCostCollectionReq.getMainDataId());
                    collectionFeeJson.setAdjustType(1);
                    collectionFeeJson.setTotalAmount(selectTypeDTO.getTotalAmount().multiply(new BigDecimal(seriesTripDefaultCostCollectionReq.getExchangeRate())).setScale(2,BigDecimal.ROUND_HALF_UP));
                    collectionFeeJsonList.add(collectionFeeJson);

                    //累计代收费用
                    collectionFee = collectionFee.add(selectTypeDTO.getTotalAmount());
                    //应收=团费+代收+调整+其他
                    totalReceivables = ((groupFee.add(collectionFee)).add(adjustmentCost)).add(otherAmount);
                    //未收=应收-实收
                    remainingReceivables = totalReceivables.subtract(totalPaidIn);
                }
            }

            if (collectionFeeJsonList.size() > 0) {
                touristInfo.setCollectionFeeJson(JSON.toJSONString(collectionFeeJsonList));
            }

            //代收费用
            orderCollectionFee = orderCollectionFee.add(collectionFee);
            //应收=团费+代收+调整+其他
            orderTotalReceivables = ((orderGroupFee.add(orderCollectionFee)).add(orderAdjustmentCost)).add(orderOtherAmount);
            //未收=应收-实收
            orderRemainingReceivables = orderTotalReceivables.subtract(orderTotalPaidIn);

        }
        if (otherFeeSaveBatchReqList.size() > 0){
            Boolean aBoolean = iSeriesOrderTouristOtherFeeService.saveBatch(otherFeeSaveBatchReqList);
            if (!aBoolean){
                throw new BusinessException(SystemError.SYS_408);
            }
        }

        updateObject.setId(touristInfo.getId());
        //游客统计
        updateObject.setGroupFee(groupFee);
        updateObject.setTotalReceivables(totalReceivables);
        updateObject.setTotalPaidIn(totalPaidIn);
        updateObject.setRefundAmount(refundAmount);
        updateObject.setCollectionFee(collectionFee);
        updateObject.setAdjustmentCost(adjustmentCost);
        updateObject.setOtherAmount(otherAmount);
        updateObject.setReceiptedAmount(receiptedAmount);
        updateObject.setRemainingReceivables(remainingReceivables);
        updateObject.setPeopleType(1);
        if (StringUtils.isNotBlank(req.getCnName()) && StringUtils.isNotBlank(req.getCnSurname())){
            updateObject.setCnFullname(req.getCnSurname() + req.getCnName());
        }
        if (StringUtils.isNotBlank(req.getEnName()) && StringUtils.isNotBlank(req.getEnSurname())){
            updateObject.setEnFullname(req.getEnSurname() + req.getEnName());
        }
        updateObject.setIsFullInfo(ISCode.YES.getCode());

        if(req.getCertificateList() != null) {
            int size = req.getCertificateList().size();
            if (size >= 1) {
                SeriesOrderTouristInfoEditCertificateReq certificateReq = req.getCertificateList().get(0);
                updateObject.setCertificateType1(certificateReq.getCertificateType());
                updateObject.setCertificateTypeId1(certificateReq.getCertificateTypeId());
                updateObject.setCertificateNumber1(certificateReq.getCertificateNumber());
                updateObject.setCertificateValidDate1(certificateReq.getCertificateValidDate());
                updateObject.setCertificatePlace1(certificateReq.getCertificatePlace());
                updateObject.setCertificatePlaceId1(certificateReq.getCertificatePlaceId());
            } else {
                updateObject.setCertificateType1(null);
                updateObject.setCertificateTypeId1(null);
                updateObject.setCertificateNumber1(null);
                updateObject.setCertificateValidDate1(null);
                updateObject.setCertificatePlace1(null);
                updateObject.setCertificatePlaceId1(null);

                updateObject.setCertificateType2(null);
                updateObject.setCertificateTypeId2(null);
                updateObject.setCertificateNumber2(null);
                updateObject.setCertificateValidDate2(null);
                updateObject.setCertificatePlace2(null);
                updateObject.setCertificatePlaceId2(null);

                updateObject.setCertificateType3(null);
                updateObject.setCertificateTypeId3(null);
                updateObject.setCertificateNumber3(null);
                updateObject.setCertificateValidDate3(null);
                updateObject.setCertificatePlace3(null);
                updateObject.setCertificatePlaceId3(null);
            }
            if (size >= 2) {
                SeriesOrderTouristInfoEditCertificateReq certificateReq = req.getCertificateList().get(1);
                updateObject.setCertificateType2(certificateReq.getCertificateType());
                updateObject.setCertificateTypeId2(certificateReq.getCertificateTypeId());
                updateObject.setCertificateNumber2(certificateReq.getCertificateNumber());
                updateObject.setCertificateValidDate2(certificateReq.getCertificateValidDate());
                updateObject.setCertificatePlace2(certificateReq.getCertificatePlace());
                updateObject.setCertificatePlaceId2(certificateReq.getCertificatePlaceId());
            } else {
                updateObject.setCertificateType2(null);
                updateObject.setCertificateTypeId2(null);
                updateObject.setCertificateNumber2(null);
                updateObject.setCertificateValidDate2(null);
                updateObject.setCertificatePlace2(null);
                updateObject.setCertificatePlaceId2(null);

                updateObject.setCertificateType3(null);
                updateObject.setCertificateTypeId3(null);
                updateObject.setCertificateNumber3(null);
                updateObject.setCertificateValidDate3(null);
                updateObject.setCertificatePlace3(null);
                updateObject.setCertificatePlaceId3(null);
            }
            if (size >= 3) {
                SeriesOrderTouristInfoEditCertificateReq certificateReq = req.getCertificateList().get(2);
                updateObject.setCertificateType3(certificateReq.getCertificateType());
                updateObject.setCertificateTypeId3(certificateReq.getCertificateTypeId());
                updateObject.setCertificateNumber3(certificateReq.getCertificateNumber());
                updateObject.setCertificateValidDate3(certificateReq.getCertificateValidDate());
                updateObject.setCertificatePlace3(certificateReq.getCertificatePlace());
                updateObject.setCertificatePlaceId3(certificateReq.getCertificatePlaceId());
            } else {
                updateObject.setCertificateType3(null);
                updateObject.setCertificateTypeId3(null);
                updateObject.setCertificateNumber3(null);
                updateObject.setCertificateValidDate3(null);
                updateObject.setCertificatePlace3(null);
                updateObject.setCertificatePlaceId3(null);
            }
        }
        boolean update = updateById(updateObject);
        if (!update){
            throw new BusinessException(SystemError.SYS_408);
        }

        //订单统计
        /*statistics.setTotalTourFee(orderGroupFee);
        statistics.setTotalReceivables(orderTotalReceivables);
        statistics.setTotalPaidIn(orderTotalPaidIn);
        statistics.setRefundAmount(orderRefundAmount);
        statistics.setCollectionFee(orderCollectionFee);
        statistics.setAdjustmentCost(orderAdjustmentCost);
        statistics.setOtherAmount(orderOtherAmount);
        statistics.setReceiptedAmount(orderReceiptedAmount);
        statistics.setRemainingReceivables(orderRemainingReceivables);
        int updateStatistics = seriesOrderAmountStatisticsMapper.updateById(statistics);*/

        //是否应用全部
        if (Objects.equals(req.getIsApplyAll(),1)){
            //紧急联系人应用全部
            if (StringUtils.isBlank(req.getEmergencyContactName()) || StringUtils.isBlank(req.getEmergencyMobileAreaCode()) || StringUtils.isBlank(req.getEmergencyMobile())){
                throw new BusinessException(SystemError.CUSTOM_ORDER_4005);
            }
            //批量更新紧急联系人
            seriesOrderTouristInfoMapper.applyEmergencyAll(req.getOrderId(),req.getEmergencyContactName(),req.getEmergencyMobileAreaCode(),req.getEmergencyMobile());
        }else{
            touristInfo.setEmergencyContactName(req.getEmergencyContactName());
            touristInfo.setEmergencyMobileAreaCode(req.getEmergencyMobileAreaCode());
            touristInfo.setEmergencyMobile(req.getEmergencyMobile());
        }
        return Result.success(touristInfo.getId());
    }

    /**
     * 列表
     */
    @Override
    public PageResponse<SeriesOrderTouristInfoDTO> list(SeriesOrderTouristInfoListReq seriesOrderTouristInfoListReq) {
        IPage<SeriesOrderTouristInfoListReq> page = new Page<>(seriesOrderTouristInfoListReq.getPageNo(), seriesOrderTouristInfoListReq.getPageSize());
        IPage<SeriesOrderTouristInfoDTO> seriesOrderDTOIPage = seriesOrderTouristInfoMapper.selectListBySelective(page, seriesOrderTouristInfoListReq);
        for (SeriesOrderTouristInfoDTO record : seriesOrderDTOIPage.getRecords()) {
            List<SeriesOrderTouristInfoCertificateDTO> certificateDTOList = new ArrayList<>();
            if (record.getCertificateType1() != null || record.getCertificateTypeId1() != null || record.getCertificateNumber1() != null
                    || record.getCertificateValidDate1() != null || record.getCertificatePlace1() != null
                    || record.getCertificatePlaceId1() != null) {
                SeriesOrderTouristInfoCertificateDTO certificateDTO = new SeriesOrderTouristInfoCertificateDTO();
                certificateDTO.setCertificateType(record.getCertificateType1());
                certificateDTO.setCertificateTypeId(record.getCertificateTypeId1());
                certificateDTO.setCertificateNumber(record.getCertificateNumber1());
                certificateDTO.setCertificateValidDate(record.getCertificateValidDate1());
                certificateDTO.setCertificatePlace(record.getCertificatePlace1());
                certificateDTO.setCertificatePlaceId(record.getCertificatePlaceId1());
                certificateDTOList.add(certificateDTO);
            }
            if (record.getCertificateType2() != null || record.getCertificateTypeId2() != null || record.getCertificateNumber2() != null
                    || record.getCertificateValidDate2() != null || record.getCertificatePlace2() != null
                    || record.getCertificatePlaceId2() != null) {
                SeriesOrderTouristInfoCertificateDTO certificateDTO = new SeriesOrderTouristInfoCertificateDTO();
                certificateDTO.setCertificateType(record.getCertificateType2());
                certificateDTO.setCertificateTypeId(record.getCertificateTypeId2());
                certificateDTO.setCertificateNumber(record.getCertificateNumber2());
                certificateDTO.setCertificateValidDate(record.getCertificateValidDate2());
                certificateDTO.setCertificatePlace(record.getCertificatePlace2());
                certificateDTO.setCertificatePlaceId(record.getCertificatePlaceId2());
                certificateDTOList.add(certificateDTO);
            }
            if (record.getCertificateType3() != null || record.getCertificateTypeId3() != null || record.getCertificateNumber3() != null
                    || record.getCertificateValidDate3() != null || record.getCertificatePlace3() != null
                    || record.getCertificatePlaceId3() != null) {
                SeriesOrderTouristInfoCertificateDTO certificateDTO = new SeriesOrderTouristInfoCertificateDTO();
                certificateDTO.setCertificateType(record.getCertificateType3());
                certificateDTO.setCertificateTypeId(record.getCertificateTypeId3());
                certificateDTO.setCertificateNumber(record.getCertificateNumber3());
                certificateDTO.setCertificateValidDate(record.getCertificateValidDate3());
                certificateDTO.setCertificatePlace(record.getCertificatePlace3());
                certificateDTO.setCertificatePlaceId(record.getCertificatePlaceId3());
                certificateDTOList.add(certificateDTO);
            }
            record.setCertificateList(certificateDTOList);
        }


        PageResponse<SeriesOrderTouristInfoDTO> seriesOrderDTOPage = new PageResponse<>(seriesOrderDTOIPage.getRecords(),
                seriesOrderDTOIPage.getCurrent() == 1,
                seriesOrderDTOIPage.getTotal() <= (seriesOrderDTOIPage.getCurrent() * seriesOrderDTOIPage.getSize()),
                seriesOrderDTOIPage.getTotal(), seriesOrderDTOIPage.getCurrent(),
                seriesOrderDTOIPage.getSize());
        return seriesOrderDTOPage;
    }

    /**
     * 收款列表
     *
     * @param req
     * @return
     */
    @Override
    public PageResponse<CustomOrderTouristInfoListCollectionDTO> listCollection(CustomOrderIdReq req) {
        IPage<CustomOrderIdReq> pageParam = new Page<>(req.getPageNo(), req.getPageSize());
        IPage<CustomOrderTouristInfoListCollectionDTO> pageResult = seriesOrderTouristInfoMapper.queryTouristCollectionPage(pageParam, req.getId());
        List<CustomOrderTouristInfoListCollectionDTO> list = pageResult.getRecords();
        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(list)){
            list.forEach(dto -> {
                if (StringUtils.isNotBlank(dto.getCollectionFeeJson())){
                    dto.setCollectionFeeDTOList(JSON.parseArray(dto.getCollectionFeeJson(), TouristCollectionFeeJson.class));
                }
                //其他费用列表
                List<CustomOrderTouristOtherFeeDTO> discountList = seriesOrderTouristOtherFeeMapper.queryByTourist(dto.getId());
                dto.setOtherFeeDTOList(discountList);
            });
        }
        PageResponse<CustomOrderTouristInfoListCollectionDTO> pageResponse = new PageResponse<>(list,
                pageResult.getCurrent() == 1,
                pageResult.getTotal() <= (pageResult.getCurrent() * pageResult.getSize()),
                pageResult.getTotal(), pageResult.getCurrent(),
                pageResult.getSize());
        return pageResponse;
    }

    /**
     * 列表收款团期
     */
    @Override
    public PageResponse<SeriesOrderTouristInfoListCollectionTripDTO> listCollectionTrip(SeriesOrderTouristInfoListCollectionTripReq req) {
        IPage<SeriesOrderTouristInfoListCollectionTripReq> pageParam = new Page<>(req.getPageNo(), req.getPageSize());
        IPage<SeriesOrderTouristInfoListCollectionTripDTO> pageResult = seriesOrderTouristInfoMapper.selectListCollectionTripBySelective(pageParam, req);
        PageResponse<SeriesOrderTouristInfoListCollectionTripDTO> pageResponse = new PageResponse<>(pageResult.getRecords(),
                pageResult.getCurrent() == 1,
                pageResult.getTotal() <= (pageResult.getCurrent() * pageResult.getSize()),
                pageResult.getTotal(), pageResult.getCurrent(),
                pageResult.getSize());
        return pageResponse;
    }

    /**
     * 添加
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(SeriesOrderTouristInfoAddReq req) {
        Long orderId = req.getOrderId();
        //游客
        long touristId = IdWorker.getId();
        LocalDateTime now = LocalDateTime.now();

        //订单统计
        QueryWrapper<SeriesOrderAmountStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeriesOrderAmountStatistics::getOrderId, orderId);
        SeriesOrderAmountStatistics statistics = seriesOrderAmountStatisticsMapper.selectOne(queryWrapper);

        SeriesOrder dbOrder = seriesOrderMapper.selectById(orderId);
        if(dbOrder == null || Objects.equals(dbOrder.getIsDeleted(),1)) {
            return Result.failed(SystemError.SYS_411);
        }

        /*if(!Objects.equals(dbOrder.getPlaceOrderStatus(), PlaceOrderStatusCode.CONFIRM.getCode())) {
            return Result.failed(SeriesOrderErrorCode.STATUS_ERROR);
        }*/

        SeriesTripScheduleDTO tripScheduleDTO = iSeriesTripScheduleService.getTripScheduleId(req.getScheduleId());

        //团费
        BigDecimal orderGroupFee = statistics.getTotalTourFee();
        //应收
        BigDecimal orderTotalReceivables = statistics.getTotalReceivables();
        //实收
        BigDecimal orderTotalPaidIn = statistics.getTotalPaidIn();
        //已退款
        BigDecimal orderRefundAmount = statistics.getRefundAmount();
        //代收费用
        BigDecimal orderCollectionFee = statistics.getCollectionFee();
        //调整费用
        BigDecimal orderAdjustmentCost = statistics.getAdjustmentCost();
        //其他金额
        BigDecimal orderOtherAmount = statistics.getOtherAmount();
        //已出单据金额
        BigDecimal orderReceiptedAmount = statistics.getReceiptedAmount();
        //未收
        BigDecimal orderRemainingReceivables = statistics.getRemainingReceivables();

        Integer totalPeople = dbOrder.getTotalPeople(); //++

        List<SeriesOrderTouristInfoSaveBatchReq> touristInfoSaveBatchReqList = new ArrayList<>();
        List<SeriesOrderTouristOtherFeeSaveBatchReq> otherFeeSaveBatchReqList = new ArrayList<>();
        List<TouristCollectionFeeJson> collectionFeeJsonList = new ArrayList<>();
        SeriesOrderTouristInfoSaveBatchReq touristInfoSaveBatchReq = new SeriesOrderTouristInfoSaveBatchReq();
        if(Objects.equals(tripScheduleDTO.getCostSharingType(), CostSharingType.DEFAULT.getCode())) {
            //默认模板
            TripScheduleDefaultCostDTO tripScheduleDefaultCostDTO = tripScheduleDTO.getTripScheduleDefaultCost();
            SeriesTripScheduleSellingPriceDTO seriesTripScheduleSellingPriceDTO = tripScheduleDefaultCostDTO.getSeriesTripScheduleSellingPriceDTO();
            List<SeriesTripScheduleDefaultCostCollectionDTO> costCollectionList = tripScheduleDefaultCostDTO.getCostCollectionList();

            //团费
            BigDecimal groupFee = seriesTripScheduleSellingPriceDTO.getGroupCustomerPrice();
            //获取加幅后的团费
            //下单类型（0 直客下单，1 代理商下单）
            if (Objects.equals(dbOrder.getOrderType(),0)){
                groupFee = iSeriesTripScheduleService.getAddGroupFee(dbOrder.getOrderType(),req.getScheduleId(),groupFee,req.getUserId());
            }else if (Objects.equals(dbOrder.getOrderType(),1)){
                groupFee = iSeriesTripScheduleService.getAddGroupFee(dbOrder.getOrderType(),req.getScheduleId(),groupFee,dbOrder.getAgentId());
            }
            //应收
            BigDecimal totalReceivables = new BigDecimal(0);
            //实收
            BigDecimal totalPaidIn = new BigDecimal(0);
            //已退款
            BigDecimal refundAmount = new BigDecimal(0);
            //代收费用
            BigDecimal collectionFee = new BigDecimal(0);
            //调整费用
            BigDecimal adjustmentCost = new BigDecimal(0);
            //其他金额
            BigDecimal otherAmount = new BigDecimal(0);
            //已出单据金额
            BigDecimal receiptedAmount = new BigDecimal(0);
            //未收
            BigDecimal remainingReceivables = new BigDecimal(0);

            for (SeriesTripScheduleDefaultCostCollectionDTO seriesTripScheduleDefaultCostCollectionDTO : costCollectionList) {
                SeriesTripScheduleDefaultCostTouristTypeDTO selectTypeDTO = null;

                //判断代收费用中是否有相同游客类型的代收费用
                for (SeriesTripScheduleDefaultCostTouristTypeDTO typeDTO : seriesTripScheduleDefaultCostCollectionDTO.getCostCollectionTypeList()) {
                    if (Objects.equals(typeDTO.getTouristTypeId(), req.getMainDataId())) {//++
                        selectTypeDTO = typeDTO;
                        break;
                    }
                }

                if (selectTypeDTO == null) {
                    continue;
                }

                TouristCollectionFeeJson collectionFeeJson = new TouristCollectionFeeJson();
                collectionFeeJson.setProjectName(seriesTripScheduleDefaultCostCollectionDTO.getProjectName());
                collectionFeeJson.setMainDataId(seriesTripScheduleDefaultCostCollectionDTO.getMainDataId());
                collectionFeeJson.setAdjustType(1);
                collectionFeeJson.setTotalAmount(selectTypeDTO.getTotalAmount().multiply(new BigDecimal(seriesTripScheduleDefaultCostCollectionDTO.getExchangeRate())).setScale(2,BigDecimal.ROUND_HALF_UP));
                collectionFeeJsonList.add(collectionFeeJson);

                //累计代收费用
                collectionFee = collectionFee.add(selectTypeDTO.getTotalAmount());
            }

            if (collectionFeeJsonList.size() > 0){
                touristInfoSaveBatchReq.setCollectionFeeJson(JSON.toJSONString(collectionFeeJsonList));
            }
            //其他费用


            //调整费用

            //应收=团费+代收+调整+其他
            totalReceivables = ((groupFee.add(collectionFee)).add(adjustmentCost)).add(otherAmount);
            //未收=应收-实收
            remainingReceivables = totalReceivables.subtract(totalPaidIn);

            touristInfoSaveBatchReq.setId(touristId);
            touristInfoSaveBatchReq.setOrderId(orderId);
            touristInfoSaveBatchReq.setScheduleId(dbOrder.getScheduleId());
            touristInfoSaveBatchReq.setMainDataId(req.getMainDataId()); //++
            touristInfoSaveBatchReq.setTouristTypeName(req.getTouristTypeName());
            touristInfoSaveBatchReq.setCnSurname(req.getCnSurname());
            touristInfoSaveBatchReq.setCnName(req.getCnName());
            touristInfoSaveBatchReq.setEnSurname(req.getEnSurname());
            touristInfoSaveBatchReq.setEnName(req.getEnName());
            touristInfoSaveBatchReq.setNationId(req.getNationId());
            touristInfoSaveBatchReq.setNation(req.getNation());
            touristInfoSaveBatchReq.setGender(req.getGender());
            touristInfoSaveBatchReq.setMobileAreaCode(req.getMobileAreaCode());
            touristInfoSaveBatchReq.setMobile(req.getMobile());
            touristInfoSaveBatchReq.setBirthday(req.getBirthday());
            touristInfoSaveBatchReq.setEmail(req.getEmail());
            touristInfoSaveBatchReq.setRemark(req.getRemark());
            if (StringUtils.isNotBlank(req.getCnName()) && StringUtils.isNotBlank(req.getCnSurname())){
                touristInfoSaveBatchReq.setCnFullname(req.getCnSurname() + req.getCnName());
            }
            if (StringUtils.isNotBlank(req.getEnName()) && StringUtils.isNotBlank(req.getEnSurname())){
                touristInfoSaveBatchReq.setEnFullname(req.getEnSurname() + req.getEnName());
            }

            touristInfoSaveBatchReq.setPayStatus(PayStatusCode.WAIT.getCode());
            touristInfoSaveBatchReq.setNoshow(LockStatusCode.NO.getCode());
            touristInfoSaveBatchReq.setLockStatus(LockStatusCode.NO.getCode());
            touristInfoSaveBatchReq.setIsDeleted(IsDeletedCode.NO.getCode());
            touristInfoSaveBatchReq.setGmtCreate(now);
            touristInfoSaveBatchReq.setGmtModified(now);
            touristInfoSaveBatchReq.setCreateId(req.getUserId());
            touristInfoSaveBatchReq.setModifiedId(req.getUserId());
            touristInfoSaveBatchReq.setIsFullInfo(ISCode.YES.getCode());
            touristInfoSaveBatchReq.setCertificateList(EntityUtil.copyList(req.getCertificateList(), SeriesOrderTouristInfoSaveBatchCertificateReq.class));
            //游客统计
            touristInfoSaveBatchReq.setGroupFee(groupFee);
            touristInfoSaveBatchReq.setTotalReceivables(totalReceivables);
            touristInfoSaveBatchReq.setTotalPaidIn(totalPaidIn);
            touristInfoSaveBatchReq.setRefundAmount(refundAmount);
            touristInfoSaveBatchReq.setCollectionFee(collectionFee);
            touristInfoSaveBatchReq.setAdjustmentCost(adjustmentCost);
            touristInfoSaveBatchReq.setOtherAmount(otherAmount);
            touristInfoSaveBatchReq.setReceiptedAmount(receiptedAmount);
            touristInfoSaveBatchReq.setRemainingReceivables(remainingReceivables);
            touristInfoSaveBatchReq.setIsReceiptCalculated(ISCode.NO.getCode());
            touristInfoSaveBatchReq.setBuyInsurance(ISCode.NO.getCode());
            touristInfoSaveBatchReq.setBuyVisa(0);

            //是否应用全部
            if (Objects.equals(req.getIsApplyAll(),1)){
                //紧急联系人应用全部
                if (StringUtils.isBlank(req.getEmergencyContactName()) || StringUtils.isBlank(req.getEmergencyMobileAreaCode()) || StringUtils.isBlank(req.getEmergencyMobile())){
                    throw new BusinessException(SystemError.CUSTOM_ORDER_4005);
                }
                //批量更新紧急联系人
                seriesOrderTouristInfoMapper.applyEmergencyAll(req.getOrderId(),req.getEmergencyContactName(),req.getEmergencyMobileAreaCode(),req.getEmergencyMobile());
            }

            touristInfoSaveBatchReq.setEmergencyContactName(req.getEmergencyContactName());
            touristInfoSaveBatchReq.setEmergencyMobileAreaCode(req.getEmergencyMobileAreaCode());
            touristInfoSaveBatchReq.setEmergencyMobile(req.getEmergencyMobile());

            touristInfoSaveBatchReqList.add(touristInfoSaveBatchReq);

            //人数
            totalPeople++;
            //团费
            orderGroupFee = orderGroupFee.add(groupFee);
            //应收
            orderTotalReceivables = orderTotalReceivables.add(totalReceivables);
            //实收
            orderTotalPaidIn = orderTotalPaidIn.add(totalPaidIn);
            //已退款
            orderRefundAmount = orderRefundAmount.add(refundAmount);
            //代收费用
            orderCollectionFee = orderCollectionFee.add(collectionFee);
            //调整费用
            orderAdjustmentCost = orderAdjustmentCost.add(adjustmentCost);
            //其他金额
            orderOtherAmount = orderOtherAmount.add(otherAmount);
            //已出单据金额
            orderReceiptedAmount = orderReceiptedAmount.add(receiptedAmount);
            //未收
            orderRemainingReceivables = orderRemainingReceivables.add(remainingReceivables);

        }else if(Objects.equals(tripScheduleDTO.getCostSharingType(), CostSharingType.CUSTOM.getCode())) {
            //自定义
            TripCustomCostReq tripCustomCostReq = tripScheduleDTO.getTripCustomCostReq();
            List<TripCustomSalePriceReq> customSalePriceList =  tripCustomCostReq.getCustomSalePriceList();;
            List<SeriesTripDefaultCostCollectionReq> customCostCollectionList =  tripCustomCostReq.getCostCollectionList();

            //团费
            TripCustomSalePriceReq selectTripCustomSalePriceReq = null;
            A:
            for (TripCustomSalePriceReq tripCustomSalePriceReq : customSalePriceList) {
                if (Objects.equals(tripCustomSalePriceReq.getMainDataId(), req.getMainDataId())) {
                    if (Objects.equals(tripCustomSalePriceReq.getDateType(), DataType.WEEK.getCode())) {
                        for (Integer checkWeekDay : tripCustomSalePriceReq.getCheckWeekDays()) {
                            if (Objects.equals(tripScheduleDTO.getDepartureDate().getDayOfWeek().getValue(), checkWeekDay)) {
                                selectTripCustomSalePriceReq = tripCustomSalePriceReq;
                                break A;
                            }
                        }
                    } else if (Objects.equals(tripCustomSalePriceReq.getDateType(), DataType.DATE.getCode())) {
                        if (tripScheduleDTO.getDepartureDate().compareTo(tripCustomSalePriceReq.getDateBegin()) >= 0
                                && tripScheduleDTO.getDepartureDate().compareTo(tripCustomSalePriceReq.getDateEnd()) <= 0) {
                            selectTripCustomSalePriceReq = tripCustomSalePriceReq;
                            break A;
                        }
                    }
                }
            }
             if (selectTripCustomSalePriceReq == null) {
                throw new BusinessException(SystemError.SYS_411);
            }

            //团费
            BigDecimal groupFee = selectTripCustomSalePriceReq.getGroupCustomerPrice();
            //获取加幅后的团费
            //下单类型（0 直客下单，1 代理商下单）
            if (Objects.equals(dbOrder.getOrderType(),0)){
                groupFee = iSeriesTripScheduleService.getAddGroupFee(dbOrder.getOrderType(),req.getScheduleId(),groupFee,req.getUserId());
            }else if (Objects.equals(dbOrder.getOrderType(),1)){
                groupFee = iSeriesTripScheduleService.getAddGroupFee(dbOrder.getOrderType(),req.getScheduleId(),groupFee,dbOrder.getAgentId());
            }
            //应收
            BigDecimal totalReceivables = new BigDecimal(0);
            //实收
            BigDecimal totalPaidIn = new BigDecimal(0);
            //已退款
            BigDecimal refundAmount = new BigDecimal(0);
            //代收费用
            BigDecimal collectionFee = new BigDecimal(0);
            //调整费用
            BigDecimal adjustmentCost = new BigDecimal(0);
            //其他金额
            BigDecimal otherAmount = new BigDecimal(0);
            //已出单据金额
            BigDecimal receiptedAmount = new BigDecimal(0);
            //未收
            BigDecimal remainingReceivables = new BigDecimal(0);

            for (SeriesTripDefaultCostCollectionReq seriesTripDefaultCostCollectionReq : customCostCollectionList) {
                SeriesTripDefaultCostCollectionTypeReq selectTypeDTO = null;

                //判断代收费用中是否有相同游客类型的代收费用
                for (SeriesTripDefaultCostCollectionTypeReq typeDTO : seriesTripDefaultCostCollectionReq.getCostCollectionTypeList()) {
                    if (Objects.equals(typeDTO.getTouristTypeId(), req.getMainDataId())) {
                        selectTypeDTO = typeDTO;
                        break;
                    }
                }

                if (selectTypeDTO == null) {
                    continue;
                }

                TouristCollectionFeeJson collectionFeeJson = new TouristCollectionFeeJson();
                collectionFeeJson.setProjectName(seriesTripDefaultCostCollectionReq.getProjectName());
                collectionFeeJson.setMainDataId(seriesTripDefaultCostCollectionReq.getMainDataId());
                collectionFeeJson.setAdjustType(1);
                collectionFeeJson.setTotalAmount(selectTypeDTO.getTotalAmount().multiply(new BigDecimal(seriesTripDefaultCostCollectionReq.getExchangeRate())).setScale(2,BigDecimal.ROUND_HALF_UP));
                collectionFeeJsonList.add(collectionFeeJson);

                //累计代收费用
                collectionFee = collectionFee.add(selectTypeDTO.getTotalAmount());
            }

            if (collectionFeeJsonList.size() > 0){
                touristInfoSaveBatchReq.setCollectionFeeJson(JSON.toJSONString(collectionFeeJsonList));
            }
            //其他费用


            //调整费用

            //应收=团费+代收+调整+其他
            totalReceivables = ((groupFee.add(collectionFee)).add(adjustmentCost)).add(otherAmount);
            //未收=应收-实收
            remainingReceivables = totalReceivables.subtract(totalPaidIn);

            touristInfoSaveBatchReq.setId(touristId);
            touristInfoSaveBatchReq.setOrderId(orderId);
            touristInfoSaveBatchReq.setScheduleId(dbOrder.getScheduleId());
            touristInfoSaveBatchReq.setMainDataId(req.getMainDataId()); //++
            touristInfoSaveBatchReq.setTouristTypeName(req.getTouristTypeName());
            touristInfoSaveBatchReq.setCnSurname(req.getCnSurname());
            touristInfoSaveBatchReq.setCnName(req.getCnName());
            touristInfoSaveBatchReq.setEnSurname(req.getEnSurname());
            touristInfoSaveBatchReq.setEnName(req.getEnName());
            touristInfoSaveBatchReq.setNationId(req.getNationId());
            touristInfoSaveBatchReq.setNation(req.getNation());
            touristInfoSaveBatchReq.setGender(req.getGender());
            touristInfoSaveBatchReq.setMobileAreaCode(req.getMobileAreaCode());
            touristInfoSaveBatchReq.setMobile(req.getMobile());
            touristInfoSaveBatchReq.setBirthday(req.getBirthday());
            touristInfoSaveBatchReq.setEmail(req.getEmail());
            touristInfoSaveBatchReq.setRemark(req.getRemark());
            if (StringUtils.isNotBlank(req.getCnName()) && StringUtils.isNotBlank(req.getCnSurname())){
                touristInfoSaveBatchReq.setCnFullname(req.getCnSurname() + req.getCnName());
            }
            if (StringUtils.isNotBlank(req.getEnName()) && StringUtils.isNotBlank(req.getEnSurname())){
                touristInfoSaveBatchReq.setEnFullname(req.getEnSurname() + req.getEnName());
            }

            touristInfoSaveBatchReq.setPayStatus(PayStatusCode.WAIT.getCode());
            touristInfoSaveBatchReq.setNoshow(LockStatusCode.NO.getCode());
            touristInfoSaveBatchReq.setLockStatus(LockStatusCode.NO.getCode());
            touristInfoSaveBatchReq.setIsDeleted(IsDeletedCode.NO.getCode());
            touristInfoSaveBatchReq.setGmtCreate(now);
            touristInfoSaveBatchReq.setGmtModified(now);
            touristInfoSaveBatchReq.setCreateId(req.getUserId());
            touristInfoSaveBatchReq.setModifiedId(req.getUserId());
            touristInfoSaveBatchReq.setIsFullInfo(ISCode.YES.getCode());
            touristInfoSaveBatchReq.setCertificateList(EntityUtil.copyList(req.getCertificateList(), SeriesOrderTouristInfoSaveBatchCertificateReq.class));
            //游客统计
            touristInfoSaveBatchReq.setGroupFee(groupFee);
            touristInfoSaveBatchReq.setTotalReceivables(totalReceivables);
            touristInfoSaveBatchReq.setTotalPaidIn(totalPaidIn);
            touristInfoSaveBatchReq.setRefundAmount(refundAmount);
            touristInfoSaveBatchReq.setCollectionFee(collectionFee);
            touristInfoSaveBatchReq.setAdjustmentCost(adjustmentCost);
            touristInfoSaveBatchReq.setOtherAmount(otherAmount);
            touristInfoSaveBatchReq.setReceiptedAmount(receiptedAmount);
            touristInfoSaveBatchReq.setRemainingReceivables(remainingReceivables);
            touristInfoSaveBatchReq.setIsReceiptCalculated(ISCode.NO.getCode());
            touristInfoSaveBatchReq.setBuyInsurance(ISCode.NO.getCode());
            touristInfoSaveBatchReq.setBuyVisa(0);

            //是否应用全部
            if (Objects.equals(req.getIsApplyAll(),1)){
                //紧急联系人应用全部
                if (StringUtils.isBlank(req.getEmergencyContactName()) || StringUtils.isBlank(req.getEmergencyMobileAreaCode()) || StringUtils.isBlank(req.getEmergencyMobile())){
                    throw new BusinessException(SystemError.CUSTOM_ORDER_4005);
                }
                //批量更新紧急联系人
                seriesOrderTouristInfoMapper.applyEmergencyAll(req.getOrderId(),req.getEmergencyContactName(),req.getEmergencyMobileAreaCode(),req.getEmergencyMobile());
            }
            touristInfoSaveBatchReq.setEmergencyContactName(req.getEmergencyContactName());
            touristInfoSaveBatchReq.setEmergencyMobileAreaCode(req.getEmergencyMobileAreaCode());
            touristInfoSaveBatchReq.setEmergencyMobile(req.getEmergencyMobile());

            touristInfoSaveBatchReqList.add(touristInfoSaveBatchReq);

            //人数
            totalPeople++;
            //团费
            orderGroupFee = orderGroupFee.add(groupFee);
            //实收
            orderTotalPaidIn = orderTotalPaidIn.add(totalPaidIn);
            //已退款
            orderRefundAmount = orderRefundAmount.add(refundAmount);
            //代收费用
            orderCollectionFee = orderCollectionFee.add(collectionFee);
            //调整费用
            orderAdjustmentCost = orderAdjustmentCost.add(adjustmentCost);
            //其他金额
            orderOtherAmount = orderOtherAmount.add(otherAmount);
            //已出单据金额
            orderReceiptedAmount = orderReceiptedAmount.add(receiptedAmount);
            //应收=团费+代收+调整+其他
            orderTotalReceivables = ((orderGroupFee.add(orderCollectionFee)).add(orderAdjustmentCost)).add(orderOtherAmount);
            //未收=应收-实收
            orderRemainingReceivables = orderTotalReceivables.subtract(orderTotalPaidIn);
        }

        if (touristInfoSaveBatchReqList.size() > 0){
            Boolean batch = iSeriesOrderTouristInfoService.saveBatch(touristInfoSaveBatchReqList);
            if (!batch){
                throw new BusinessException(SystemError.SYS_408);
            }
        }
        if (otherFeeSaveBatchReqList.size() > 0){
            Boolean batch = iSeriesOrderTouristOtherFeeService.saveBatch(otherFeeSaveBatchReqList);
            if (!batch){
                throw new BusinessException(SystemError.SYS_408);
            }
        }


        dbOrder.setId(orderId);
        dbOrder.setTotalPeople(totalPeople);
        dbOrder.setTotalPrice(orderGroupFee);
        dbOrder.setGmtModified(now);
        dbOrder.setModifiedId(req.getUserId());

        seriesOrderMapper.updateById(dbOrder);

        //统计
//        statistics.setScheduleId(seriesOrder.getScheduleId()); //++
//        statistics.setOrderId(orderId);
        statistics.setTotalTourFee(orderGroupFee);
        statistics.setTotalReceivables(orderTotalReceivables);
        statistics.setTotalPaidIn(orderTotalPaidIn);
        statistics.setRefundAmount(orderRefundAmount);
        statistics.setCollectionFee(orderCollectionFee);
        statistics.setAdjustmentCost(orderAdjustmentCost);
        statistics.setOtherAmount(orderOtherAmount);
        statistics.setReceiptedAmount(orderReceiptedAmount);
        statistics.setRemainingReceivables(orderRemainingReceivables);
        seriesOrderAmountStatisticsMapper.updateById(statistics);
        //更新余位数
        iSeriesTripScheduleService.substrateTouristNum(req.getScheduleId(), 1);
        return Result.success(touristId);
    }

    /**
     * Excel添加
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result excelAdd(List<SeriesOrderTouristInfoExcelAddReq> reqList, SeriesOrderTouristInfoExcelAddReq req) {

        Long orderId = req.getOrderId();
        //游客
        long touristId = IdWorker.getId();
        LocalDateTime now = LocalDateTime.now();

        //订单统计
        QueryWrapper<SeriesOrderAmountStatistics> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeriesOrderAmountStatistics::getOrderId, orderId);
        SeriesOrderAmountStatistics statistics = seriesOrderAmountStatisticsMapper.selectOne(queryWrapper);

        SeriesOrder dbOrder = seriesOrderMapper.selectById(orderId);
        if(dbOrder == null) {
            return Result.failed(SystemError.SYS_411);
        }

        if(!Objects.equals(dbOrder.getPlaceOrderStatus(), PlaceOrderStatusCode.CONFIRM.getCode())) {
            return Result.failed(SeriesOrderErrorCode.STATUS_ERROR);
        }

        SeriesTripScheduleDTO tripScheduleDTO = iSeriesTripScheduleService.getTripScheduleId(req.getScheduleId());


        List<SeriesOrderTouristInfoSaveBatchReq> touristInfoSaveBatchReqList = new ArrayList<>();
        List<SeriesOrderTouristOtherFeeSaveBatchReq> otherFeeSaveBatchReqList = new ArrayList<>();

        //团费
        BigDecimal orderGroupFee = statistics.getTotalTourFee();
        //应收
        BigDecimal orderTotalReceivables = statistics.getTotalReceivables();
        //实收
        BigDecimal orderTotalPaidIn = statistics.getTotalPaidIn();
        //已退款
        BigDecimal orderRefundAmount = statistics.getRefundAmount();
        //代收费用
        BigDecimal orderCollectionFee = statistics.getCollectionFee();
        //调整费用
        BigDecimal orderAdjustmentCost = statistics.getAdjustmentCost();
        //其他金额
        BigDecimal orderOtherAmount = statistics.getOtherAmount();
        //已出单据金额
        BigDecimal orderReceiptedAmount = statistics.getReceiptedAmount();
        //未收
        BigDecimal orderRemainingReceivables = statistics.getRemainingReceivables();

        Integer totalPeople = dbOrder.getTotalPeople(); //++

        Map<String, MainDataTouristTypeListDTO> touristTypeMap = new HashMap<>();
        Map<String, AreaTreeListDTO> areaMap = new HashMap<>();
        Map<String, MainDataRowFieldDataDTO> certificateTypeMap = new HashMap<>();
        for (SeriesOrderTouristInfoExcelAddReq tempReq : reqList) {
            SeriesOrderTouristInfoSaveBatchReq touristInfoSaveBatchReq = EntityUtil.copy(tempReq, SeriesOrderTouristInfoSaveBatchReq.class);
            touristInfoSaveBatchReq.setId(IdWorker.getId());
            touristInfoSaveBatchReq.setOrderId(req.getOrderId());
            touristInfoSaveBatchReq.setScheduleId(req.getScheduleId());

            MainDataTouristTypeListDTO touristTypeListDTO = touristTypeMap.get(tempReq.getTouristTypeName());
            if (touristTypeListDTO == null) {
                MainDataTouristTypeListReq touristTypeListReq = new MainDataTouristTypeListReq();
                touristTypeListReq.setTouristTypeName(tempReq.getTouristTypeName());
                PageResponse<MainDataTouristTypeListDTO> pageResponse = iMainDataTouristTypeService.list(touristTypeListReq);
                if (CollectionUtils.isEmpty(pageResponse.getRecords())) {
                    return Result.failed(SeriesOrderErrorCode.EXCEL_ADD_IMPORT_ERROR);
                }
                touristTypeListDTO = pageResponse.getRecords().get(0);
                touristTypeMap.put(tempReq.getTouristTypeName(), touristTypeListDTO);
            }
            touristInfoSaveBatchReq.setMainDataId(touristTypeListDTO.getId());

            touristInfoSaveBatchReq.setPayStatus(PayStatusCode.WAIT.getCode());
            touristInfoSaveBatchReq.setNoshow(LockStatusCode.NO.getCode());
            touristInfoSaveBatchReq.setLockStatus(LockStatusCode.NO.getCode());
            touristInfoSaveBatchReq.setIsDeleted(IsDeletedCode.NO.getCode());
            touristInfoSaveBatchReq.setGmtCreate(now);
            touristInfoSaveBatchReq.setGmtModified(now);
            touristInfoSaveBatchReq.setCreateId(req.getUserId());
            touristInfoSaveBatchReq.setModifiedId(req.getUserId());
            touristInfoSaveBatchReq.setIsFullInfo(ISCode.YES.getCode());
            touristInfoSaveBatchReq.setGender(GenderCode.getCode(tempReq.getGenderName()));

            AreaTreeListDTO areaTreeListDTO = areaMap.get(tempReq.getTouristTypeName());
            if (areaTreeListDTO == null) {
                AreaQueryLikeNameReq areaQueryLikeNameReq = new AreaQueryLikeNameReq();
                areaQueryLikeNameReq.setName(tempReq.getNation());
                PageResponse<AreaTreeListDTO> areaTreeListDTOPageResponse = iSysAreaService.queryAreaLikeNamePost(areaQueryLikeNameReq);
                if (CollectionUtils.isEmpty(areaTreeListDTOPageResponse.getRecords())) {
                    return Result.failed(SeriesOrderErrorCode.EXCEL_ADD_IMPORT_ERROR);
                }
                areaTreeListDTO = areaTreeListDTOPageResponse.getRecords().get(0);
                areaMap.put(tempReq.getNation(), areaTreeListDTO);
            }
            touristInfoSaveBatchReq.setNationId(areaTreeListDTO.getId());

            LocalDate birthday = null;
            try {
                if (StringUtils.isNotBlank(tempReq.getBirthdayString())) {
                    birthday = Utils.asLocalDateForString(tempReq.getBirthdayString());
                }
            } catch (Exception e) {
                throw new BusinessException(SeriesOrderErrorCode.EXCEL_ADD_DATE_FORMAT_IMPORT_ERROR);
            }
            touristInfoSaveBatchReq.setBirthday(birthday);

            List<SeriesOrderTouristInfoSaveBatchCertificateReq> certificateList = new ArrayList<>();
            if (tempReq.getCertificateType1() != null || tempReq.getCertificateTypeId1() != null || tempReq.getCertificateNumber1() != null
                    || tempReq.getCertificateValidDate1() != null || tempReq.getCertificatePlace1() != null
                    || tempReq.getCertificatePlaceId1() != null) {
                SeriesOrderTouristInfoSaveBatchCertificateReq batchCertificateReq = new SeriesOrderTouristInfoSaveBatchCertificateReq();

                MainDataRowFieldDataDTO certificateTypeDTO = certificateTypeMap.get(tempReq.getCertificateType1());
                if (certificateTypeDTO == null) {
                    MainDataRowFieldDataReq mainDataRowFieldDataReq = new MainDataRowFieldDataReq();
                    mainDataRowFieldDataReq.setTid(MainDataTableIdCode.CERTIFICATE_TYPE.getTid());
                    mainDataRowFieldDataReq.setFid(MainDataTableIdCode.CERTIFICATE_TYPE.getFid());
                    mainDataRowFieldDataReq.setName(tempReq.getCertificateType1());
                    List<MainDataRowFieldDataDTO> certificateTypeList = iMainDataTableService.queryDataFieldLikeName(mainDataRowFieldDataReq);
                    if (CollectionUtils.isEmpty(certificateTypeList)) {
                        return Result.failed(SeriesOrderErrorCode.EXCEL_ADD_IMPORT_ERROR);
                    }
                    certificateTypeDTO = certificateTypeList.get(0);
                    certificateTypeMap.put(tempReq.getCertificateType1(), certificateTypeDTO);
                }
                batchCertificateReq.setCertificateType(tempReq.getCertificateType1());
                batchCertificateReq.setCertificateTypeId(certificateTypeDTO.getId());

                batchCertificateReq.setCertificateNumber(tempReq.getCertificateNumber1());
                LocalDate certificateValidDate1 = null;
                try {
                    if (StringUtils.isNotBlank(tempReq.getCertificateValidDate1String())) {
                        certificateValidDate1 = Utils.asLocalDateForString(tempReq.getCertificateValidDate1String());
                    }
                } catch (Exception e) {
                    throw new BusinessException(SeriesOrderErrorCode.EXCEL_ADD_DATE_FORMAT_IMPORT_ERROR);
                }
                batchCertificateReq.setCertificateValidDate(certificateValidDate1);

                AreaTreeListDTO areaPlaceDTO = areaMap.get(tempReq.getCertificatePlace1());
                if (areaPlaceDTO == null) {
                    AreaQueryLikeNameReq areaQueryLikeNameReq = new AreaQueryLikeNameReq();
                    areaQueryLikeNameReq.setName(tempReq.getCertificatePlace1());
                    PageResponse<AreaTreeListDTO> areaTreeListDTOPageResponse = iSysAreaService.queryAreaLikeNamePost(areaQueryLikeNameReq);
                    if (CollectionUtils.isEmpty(areaTreeListDTOPageResponse.getRecords())) {
                        return Result.failed(SeriesOrderErrorCode.EXCEL_ADD_IMPORT_ERROR);
                    }
                    areaPlaceDTO = areaTreeListDTOPageResponse.getRecords().get(0);
                    areaMap.put(tempReq.getCertificatePlace1(), areaPlaceDTO);
                }
                batchCertificateReq.setCertificatePlace(tempReq.getCertificatePlace1());
                batchCertificateReq.setCertificatePlaceId(areaPlaceDTO.getId());
                certificateList.add(batchCertificateReq);
            }
            if (tempReq.getCertificateType2() != null || tempReq.getCertificateTypeId2() != null || tempReq.getCertificateNumber2() != null
                    || tempReq.getCertificateValidDate2() != null || tempReq.getCertificatePlace2() != null
                    || tempReq.getCertificatePlaceId2() != null) {
                SeriesOrderTouristInfoSaveBatchCertificateReq batchCertificateReq = new SeriesOrderTouristInfoSaveBatchCertificateReq();

                MainDataRowFieldDataDTO certificateTypeDTO = certificateTypeMap.get(tempReq.getCertificateType2());
                if (certificateTypeDTO == null) {
                    MainDataRowFieldDataReq mainDataRowFieldDataReq = new MainDataRowFieldDataReq();
                    mainDataRowFieldDataReq.setTid(MainDataTableIdCode.CERTIFICATE_TYPE.getTid());
                    mainDataRowFieldDataReq.setFid(MainDataTableIdCode.CERTIFICATE_TYPE.getFid());
                    mainDataRowFieldDataReq.setName(tempReq.getCertificateType2());
                    List<MainDataRowFieldDataDTO> certificateTypeList = iMainDataTableService.queryDataFieldLikeName(mainDataRowFieldDataReq);
                    if (CollectionUtils.isEmpty(certificateTypeList)) {
                        return Result.failed(SeriesOrderErrorCode.EXCEL_ADD_IMPORT_ERROR);
                    }
                    certificateTypeDTO = certificateTypeList.get(0);
                    certificateTypeMap.put(tempReq.getCertificateType2(), certificateTypeDTO);
                }
                batchCertificateReq.setCertificateType(tempReq.getCertificateType2());
                batchCertificateReq.setCertificateTypeId(certificateTypeDTO.getId());

                batchCertificateReq.setCertificateNumber(tempReq.getCertificateNumber2());
                LocalDate certificateValidDate2 = null;
                try {
                    if (StringUtils.isNotBlank(tempReq.getCertificateValidDate2String())) {
                        certificateValidDate2 = Utils.asLocalDateForString(tempReq.getCertificateValidDate2String());
                    }
                } catch (Exception e) {
                    throw new BusinessException(SeriesOrderErrorCode.EXCEL_ADD_DATE_FORMAT_IMPORT_ERROR);
                }
                batchCertificateReq.setCertificateValidDate(certificateValidDate2);

                AreaTreeListDTO areaPlaceDTO = areaMap.get(tempReq.getCertificatePlace2());
                if (areaPlaceDTO == null) {
                    AreaQueryLikeNameReq areaQueryLikeNameReq = new AreaQueryLikeNameReq();
                    areaQueryLikeNameReq.setName(tempReq.getCertificatePlace2());
                    PageResponse<AreaTreeListDTO> areaTreeListDTOPageResponse = iSysAreaService.queryAreaLikeNamePost(areaQueryLikeNameReq);
                    if (CollectionUtils.isEmpty(areaTreeListDTOPageResponse.getRecords())) {
                        return Result.failed(SeriesOrderErrorCode.EXCEL_ADD_IMPORT_ERROR);
                    }
                    areaPlaceDTO = areaTreeListDTOPageResponse.getRecords().get(0);
                    areaMap.put(tempReq.getCertificatePlace2(), areaPlaceDTO);
                }
                batchCertificateReq.setCertificatePlace(tempReq.getCertificatePlace2());
                batchCertificateReq.setCertificatePlaceId(areaPlaceDTO.getId());
                certificateList.add(batchCertificateReq);
            }
            if (tempReq.getCertificateType3() != null || tempReq.getCertificateTypeId3() != null || tempReq.getCertificateNumber3() != null
                    || tempReq.getCertificateValidDate3() != null || tempReq.getCertificatePlace3() != null
                    || tempReq.getCertificatePlaceId3() != null) {
                SeriesOrderTouristInfoSaveBatchCertificateReq batchCertificateReq = new SeriesOrderTouristInfoSaveBatchCertificateReq();

                MainDataRowFieldDataDTO certificateTypeDTO = certificateTypeMap.get(tempReq.getCertificateType3());
                if (certificateTypeDTO == null) {
                    MainDataRowFieldDataReq mainDataRowFieldDataReq = new MainDataRowFieldDataReq();
                    mainDataRowFieldDataReq.setTid(MainDataTableIdCode.CERTIFICATE_TYPE.getTid());
                    mainDataRowFieldDataReq.setFid(MainDataTableIdCode.CERTIFICATE_TYPE.getFid());
                    mainDataRowFieldDataReq.setName(tempReq.getCertificateType3());
                    List<MainDataRowFieldDataDTO> certificateTypeList = iMainDataTableService.queryDataFieldLikeName(mainDataRowFieldDataReq);
                    if (CollectionUtils.isEmpty(certificateTypeList)) {
                        return Result.failed(SeriesOrderErrorCode.EXCEL_ADD_IMPORT_ERROR);
                    }
                    certificateTypeDTO = certificateTypeList.get(0);
                    certificateTypeMap.put(tempReq.getCertificateType3(), certificateTypeDTO);
                }
                batchCertificateReq.setCertificateType(tempReq.getCertificateType3());
                batchCertificateReq.setCertificateTypeId(certificateTypeDTO.getId());

                batchCertificateReq.setCertificateNumber(tempReq.getCertificateNumber3());
                LocalDate certificateValidDate3 = null;
                try {
                    if (StringUtils.isNotBlank(tempReq.getCertificateValidDate3String())) {
                        certificateValidDate3 = Utils.asLocalDateForString(tempReq.getCertificateValidDate3String());
                    }
                } catch (Exception e) {
                    throw new BusinessException(SeriesOrderErrorCode.EXCEL_ADD_DATE_FORMAT_IMPORT_ERROR);
                }
                batchCertificateReq.setCertificateValidDate(certificateValidDate3);

                AreaTreeListDTO areaPlaceDTO = areaMap.get(tempReq.getCertificatePlace3());
                if (areaPlaceDTO == null) {
                    AreaQueryLikeNameReq areaQueryLikeNameReq = new AreaQueryLikeNameReq();
                    areaQueryLikeNameReq.setName(tempReq.getCertificatePlace3());
                    PageResponse<AreaTreeListDTO> areaTreeListDTOPageResponse = iSysAreaService.queryAreaLikeNamePost(areaQueryLikeNameReq);
                    if (CollectionUtils.isEmpty(areaTreeListDTOPageResponse.getRecords())) {
                        return Result.failed(SeriesOrderErrorCode.EXCEL_ADD_IMPORT_ERROR);
                    }
                    areaPlaceDTO = areaTreeListDTOPageResponse.getRecords().get(0);
                    areaMap.put(tempReq.getCertificatePlace3(), areaPlaceDTO);
                }
                batchCertificateReq.setCertificatePlace(tempReq.getCertificatePlace3());
                batchCertificateReq.setCertificatePlaceId(areaPlaceDTO.getId());
                certificateList.add(batchCertificateReq);
            }
            touristInfoSaveBatchReq.setCertificateList(certificateList);
            touristInfoSaveBatchReq.setIsReceiptCalculated(ISCode.NO.getCode());
            touristInfoSaveBatchReq.setBuyInsurance(ISCode.NO.getCode());

            if(Objects.equals(tripScheduleDTO.getCostSharingType(), CostSharingType.DEFAULT.getCode())) {
                //默认模板
                TripScheduleDefaultCostDTO tripScheduleDefaultCostDTO = tripScheduleDTO.getTripScheduleDefaultCost();
                SeriesTripScheduleSellingPriceDTO seriesTripScheduleSellingPriceDTO = tripScheduleDefaultCostDTO.getSeriesTripScheduleSellingPriceDTO();
                List<SeriesTripScheduleDefaultCostCollectionDTO> costCollectionList = tripScheduleDefaultCostDTO.getCostCollectionList();

                //团费
                BigDecimal groupFee = seriesTripScheduleSellingPriceDTO.getGroupCustomerPrice();
                //应收
                BigDecimal totalReceivables = new BigDecimal(0);
                //实收
                BigDecimal totalPaidIn = new BigDecimal(0);
                //已退款
                BigDecimal refundAmount = new BigDecimal(0);
                //代收费用
                BigDecimal collectionFee = new BigDecimal(0);
                //调整费用
                BigDecimal adjustmentCost = new BigDecimal(0);
                //其他金额
                BigDecimal otherAmount = new BigDecimal(0);
                //已出单据金额
                BigDecimal receiptedAmount = new BigDecimal(0);
                //未收
                BigDecimal remainingReceivables = new BigDecimal(0);

                for (SeriesTripScheduleDefaultCostCollectionDTO seriesTripScheduleDefaultCostCollectionDTO : costCollectionList) {
                    SeriesTripScheduleDefaultCostTouristTypeDTO selectTypeDTO = null;

                    //判断代收费用中是否有相同游客类型的代收费用
                    for (SeriesTripScheduleDefaultCostTouristTypeDTO typeDTO : seriesTripScheduleDefaultCostCollectionDTO.getCostCollectionTypeList()) {
                        if (Objects.equals(typeDTO.getTouristTypeId(), touristInfoSaveBatchReq.getMainDataId())) {//++
                            selectTypeDTO = typeDTO;
                            break;
                        }
                    }

                    if (selectTypeDTO == null) {
                        continue;
                    }

                    //如有,将行程代收费保存用到(订单)代收费用
                    SeriesOrderTouristOtherFeeSaveBatchReq otherFeeSaveBatchReq = new SeriesOrderTouristOtherFeeSaveBatchReq();
                    otherFeeSaveBatchReq.setFeeType(SeriesOrderTouristOtherFeeFeeTypeCode.OTHER.getCode());
                    otherFeeSaveBatchReq.setOrderId(orderId);
                    otherFeeSaveBatchReq.setTouristId(touristId);
                    otherFeeSaveBatchReq.setFeeName(seriesTripScheduleDefaultCostCollectionDTO.getProjectName());
                    otherFeeSaveBatchReq.setRelationId(seriesTripScheduleDefaultCostCollectionDTO.getId());
                    otherFeeSaveBatchReq.setAmount(selectTypeDTO.getTotalAmount());
                    otherFeeSaveBatchReq.setGmtCreate(now);
                    otherFeeSaveBatchReq.setGmtModified(now);
                    otherFeeSaveBatchReq.setCreateId(req.getUserId());
                    otherFeeSaveBatchReq.setModifiedId(req.getUserId());
                    otherFeeSaveBatchReq.setIsDeleted(IsDeletedCode.NO.getCode());
                    otherFeeSaveBatchReqList.add(otherFeeSaveBatchReq);

                    //累计代收费用
                    collectionFee = collectionFee.add(selectTypeDTO.getTotalAmount());
                }

                //其他费用


                //调整费用

                //应收=团费+代收+调整+其他
                totalReceivables = ((groupFee.add(collectionFee)).add(adjustmentCost)).add(otherAmount);
                //未收=应收-实收
                remainingReceivables = totalReceivables.subtract(totalPaidIn);

                //游客统计
                touristInfoSaveBatchReq.setGroupFee(groupFee);
                touristInfoSaveBatchReq.setTotalReceivables(totalReceivables);
                touristInfoSaveBatchReq.setTotalPaidIn(totalPaidIn);
                touristInfoSaveBatchReq.setRefundAmount(refundAmount);
                touristInfoSaveBatchReq.setCollectionFee(collectionFee);
                touristInfoSaveBatchReq.setAdjustmentCost(adjustmentCost);
                touristInfoSaveBatchReq.setOtherAmount(otherAmount);
                touristInfoSaveBatchReq.setReceiptedAmount(receiptedAmount);
                touristInfoSaveBatchReq.setRemainingReceivables(remainingReceivables);
                touristInfoSaveBatchReqList.add(touristInfoSaveBatchReq);

                //人数
                totalPeople++;
                //团费
                orderGroupFee = orderGroupFee.add(groupFee);
                //应收
                orderTotalReceivables = orderTotalReceivables.add(totalReceivables);
                //实收
                orderTotalPaidIn = orderTotalPaidIn.add(totalPaidIn);
                //已退款
                orderRefundAmount = orderRefundAmount.add(refundAmount);
                //代收费用
                orderCollectionFee = orderCollectionFee.add(collectionFee);
                //调整费用
                orderAdjustmentCost = orderAdjustmentCost.add(adjustmentCost);
                //其他金额
                orderOtherAmount = orderOtherAmount.add(otherAmount);
                //已出单据金额
                orderReceiptedAmount = orderReceiptedAmount.add(receiptedAmount);
                //未收
                orderRemainingReceivables = orderRemainingReceivables.add(remainingReceivables);

            }else if(Objects.equals(tripScheduleDTO.getCostSharingType(), CostSharingType.CUSTOM.getCode())) {
                //自定义
                TripCustomCostReq tripCustomCostReq = tripScheduleDTO.getTripCustomCostReq();
                List<TripCustomSalePriceReq> customSalePriceList =  tripCustomCostReq.getCustomSalePriceList();;
                List<SeriesTripDefaultCostCollectionReq> customCostCollectionList =  tripCustomCostReq.getCostCollectionList();

                //团费
                TripCustomSalePriceReq selectTripCustomSalePriceReq = null;
                A:
                for (TripCustomSalePriceReq tripCustomSalePriceReq : customSalePriceList) {
                    if (Objects.equals(tripCustomSalePriceReq.getMainDataId(), touristInfoSaveBatchReq.getMainDataId())) {
                        if (Objects.equals(tripCustomSalePriceReq.getDateType(), DataType.WEEK.getCode())) {
                            for (Integer checkWeekDay : tripCustomSalePriceReq.getCheckWeekDays()) {
                                if (Objects.equals(tripScheduleDTO.getDepartureDate().getDayOfWeek().getValue(), checkWeekDay)) {
                                    selectTripCustomSalePriceReq = tripCustomSalePriceReq;
                                    break A;
                                }
                            }
                        } else if (Objects.equals(tripCustomSalePriceReq.getDateType(), DataType.DATE.getCode())) {
                            if (tripScheduleDTO.getDepartureDate().compareTo(tripCustomSalePriceReq.getDateBegin()) >= 0
                                    && tripScheduleDTO.getDepartureDate().compareTo(tripCustomSalePriceReq.getDateEnd()) <= 0) {
                                selectTripCustomSalePriceReq = tripCustomSalePriceReq;
                                break A;
                            }
                        }
                    }
                }
                if (selectTripCustomSalePriceReq == null) {
                    throw new BusinessException(SystemError.SYS_411);
                }

                //团费
                BigDecimal groupFee = selectTripCustomSalePriceReq.getGroupCustomerPrice();
                //应收
                BigDecimal totalReceivables = new BigDecimal(0);
                //实收
                BigDecimal totalPaidIn = new BigDecimal(0);
                //已退款
                BigDecimal refundAmount = new BigDecimal(0);
                //代收费用
                BigDecimal collectionFee = new BigDecimal(0);
                //调整费用
                BigDecimal adjustmentCost = new BigDecimal(0);
                //其他金额
                BigDecimal otherAmount = new BigDecimal(0);
                //已出单据金额
                BigDecimal receiptedAmount = new BigDecimal(0);
                //未收
                BigDecimal remainingReceivables = new BigDecimal(0);

                for (SeriesTripDefaultCostCollectionReq seriesTripDefaultCostCollectionReq : customCostCollectionList) {
                    SeriesTripDefaultCostCollectionTypeReq selectTypeDTO = null;

                    //判断代收费用中是否有相同游客类型的代收费用
                    for (SeriesTripDefaultCostCollectionTypeReq typeDTO : seriesTripDefaultCostCollectionReq.getCostCollectionTypeList()) {
                        if (Objects.equals(typeDTO.getTouristTypeId(), touristInfoSaveBatchReq.getMainDataId())) {
                            selectTypeDTO = typeDTO;
                            break;
                        }
                    }

                    if (selectTypeDTO == null) {
                        continue;
                    }

                    //如有,将行程代收费保存用到(订单)代收费用
                    SeriesOrderTouristOtherFeeSaveBatchReq otherFeeSaveBatchReq = new SeriesOrderTouristOtherFeeSaveBatchReq();
                    otherFeeSaveBatchReq.setFeeType(SeriesOrderTouristOtherFeeFeeTypeCode.OTHER.getCode());
                    otherFeeSaveBatchReq.setOrderId(orderId);
                    otherFeeSaveBatchReq.setTouristId(touristId);
                    otherFeeSaveBatchReq.setFeeName(seriesTripDefaultCostCollectionReq.getProjectName());
                    otherFeeSaveBatchReq.setRelationId(seriesTripDefaultCostCollectionReq.getId());
                    otherFeeSaveBatchReq.setAmount(selectTypeDTO.getTotalAmount());
                    otherFeeSaveBatchReq.setGmtCreate(now);
                    otherFeeSaveBatchReq.setGmtModified(now);
                    otherFeeSaveBatchReq.setCreateId(req.getUserId());
                    otherFeeSaveBatchReq.setModifiedId(req.getUserId());
                    otherFeeSaveBatchReq.setIsDeleted(IsDeletedCode.NO.getCode());
                    otherFeeSaveBatchReqList.add(otherFeeSaveBatchReq);

                    //累计代收费用
                    collectionFee = collectionFee.add(selectTypeDTO.getTotalAmount());
                }

                //其他费用


                //调整费用

                //应收=团费+代收+调整+其他
                totalReceivables = ((groupFee.add(collectionFee)).add(adjustmentCost)).add(otherAmount);
                //未收=应收-实收
                remainingReceivables = totalReceivables.subtract(totalPaidIn);

                //游客统计
                touristInfoSaveBatchReq.setGroupFee(groupFee);
                touristInfoSaveBatchReq.setTotalReceivables(totalReceivables);
                touristInfoSaveBatchReq.setTotalPaidIn(totalPaidIn);
                touristInfoSaveBatchReq.setRefundAmount(refundAmount);
                touristInfoSaveBatchReq.setCollectionFee(collectionFee);
                touristInfoSaveBatchReq.setAdjustmentCost(adjustmentCost);
                touristInfoSaveBatchReq.setOtherAmount(otherAmount);
                touristInfoSaveBatchReq.setReceiptedAmount(receiptedAmount);
                touristInfoSaveBatchReq.setRemainingReceivables(remainingReceivables);
                touristInfoSaveBatchReqList.add(touristInfoSaveBatchReq);

                //人数
                totalPeople++;
                //团费
                orderGroupFee = orderGroupFee.add(groupFee);
                //实收
                orderTotalPaidIn = orderTotalPaidIn.add(totalPaidIn);
                //已退款
                orderRefundAmount = orderRefundAmount.add(refundAmount);
                //代收费用
                orderCollectionFee = orderCollectionFee.add(collectionFee);
                //调整费用
                orderAdjustmentCost = orderAdjustmentCost.add(adjustmentCost);
                //其他金额
                orderOtherAmount = orderOtherAmount.add(otherAmount);
                //已出单据金额
                orderReceiptedAmount = orderReceiptedAmount.add(receiptedAmount);
                //应收=团费+代收+调整+其他
                orderTotalReceivables = ((orderGroupFee.add(orderCollectionFee)).add(orderAdjustmentCost)).add(orderOtherAmount);
                //未收=应收-实收
                orderRemainingReceivables = orderTotalReceivables.subtract(orderTotalPaidIn);
            }
        }
        iSeriesOrderTouristInfoService.saveBatch(touristInfoSaveBatchReqList);
        iSeriesOrderTouristOtherFeeService.saveBatch(otherFeeSaveBatchReqList);

        dbOrder.setId(orderId);
        dbOrder.setTotalPeople(totalPeople);
        dbOrder.setTotalPrice(orderGroupFee);
        dbOrder.setGmtModified(now);
        dbOrder.setModifiedId(req.getUserId());

        seriesOrderMapper.updateById(dbOrder);

        //统计
//        statistics.setScheduleId(seriesOrder.getScheduleId()); //++
//        statistics.setOrderId(orderId);
        statistics.setTotalTourFee(orderGroupFee);
        statistics.setTotalReceivables(orderTotalReceivables);
        statistics.setTotalPaidIn(orderTotalPaidIn);
        statistics.setRefundAmount(orderRefundAmount);
        statistics.setCollectionFee(orderCollectionFee);
        statistics.setAdjustmentCost(orderAdjustmentCost);
        statistics.setOtherAmount(orderOtherAmount);
        statistics.setReceiptedAmount(orderReceiptedAmount);
        statistics.setRemainingReceivables(orderRemainingReceivables);
        seriesOrderAmountStatisticsMapper.updateById(statistics);
        return Result.success();
    }


    /**
     * 删除
     *
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result delete(SeriesOrderTouristInfoDeleteReq req) {
        //游客
        QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeriesOrderTouristInfo::getId, req.getId());
        queryWrapper.lambda().eq(SeriesOrderTouristInfo::getIsDeleted, IsDeletedCode.NO.getCode());
        SeriesOrderTouristInfo touristInfo = seriesOrderTouristInfoMapper.selectOne(queryWrapper);


        //已付款过，不能删除
        if (!touristInfo.getPayStatus().equals(PayStatusCode.WAIT.getCode())) {
            return Result.failed(SeriesOrderErrorCode.DELETE_PEOPLE_LIMIT);
        }

        //订单统计
        QueryWrapper<SeriesOrderAmountStatistics> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(SeriesOrderAmountStatistics::getOrderId, req.getOrderId());
        SeriesOrderAmountStatistics statistics = seriesOrderAmountStatisticsMapper.selectOne(queryWrapper2);

        //团费
        BigDecimal orderGroupFee = statistics.getTotalTourFee();
        //实收
        BigDecimal orderTotalPaidIn = statistics.getTotalPaidIn();
        //已退款
        BigDecimal orderRefundAmount = statistics.getRefundAmount();
        //代收费用
        BigDecimal orderCollectionFee = statistics.getCollectionFee();
        //调整费用
        BigDecimal orderAdjustmentCost = statistics.getAdjustmentCost();
        //其他金额
        BigDecimal orderOtherAmount = statistics.getOtherAmount();
        //已出单据金额
        BigDecimal orderReceiptedAmount = statistics.getReceiptedAmount();
        //应收
        BigDecimal orderTotalReceivables = statistics.getTotalReceivables();
        //未收
        BigDecimal orderRemainingReceivables = statistics.getRemainingReceivables();

        //团费
        orderGroupFee = orderGroupFee.subtract(touristInfo.getGroupFee());
        //实收
        orderTotalPaidIn = orderTotalPaidIn.subtract(touristInfo.getTotalPaidIn());
        //已退款
        orderRefundAmount = orderRefundAmount.subtract(touristInfo.getRefundAmount());
        //代收费用
        orderCollectionFee = orderCollectionFee.subtract(touristInfo.getCollectionFee());
        //调整费用
        orderAdjustmentCost = orderAdjustmentCost.subtract(touristInfo.getAdjustmentCost());
        //其他金额
        orderOtherAmount = orderOtherAmount.subtract(touristInfo.getOtherAmount());
        //已出单据金额
        orderReceiptedAmount = orderReceiptedAmount.subtract(touristInfo.getReceiptedAmount());
        //应收=团费+代收+调整+其他
        orderTotalReceivables = ((orderGroupFee.add(orderCollectionFee)).add(orderAdjustmentCost)).add(orderOtherAmount);
        //未收=应收-实收
        orderRemainingReceivables = orderTotalReceivables.subtract(orderTotalPaidIn);

        //订单统计
        statistics.setTotalTourFee(orderGroupFee);
        statistics.setTotalReceivables(orderTotalReceivables);
        statistics.setTotalPaidIn(orderTotalPaidIn);
        statistics.setRefundAmount(orderRefundAmount);
        statistics.setCollectionFee(orderCollectionFee);
        statistics.setAdjustmentCost(orderAdjustmentCost);
        statistics.setOtherAmount(orderOtherAmount);
        statistics.setReceiptedAmount(orderReceiptedAmount);
        statistics.setRemainingReceivables(orderRemainingReceivables);
        int updateOrderStatics = seriesOrderAmountStatisticsMapper.updateById(statistics);

        touristInfo.setIsDeleted(IsDeletedCode.YES.getCode());
        boolean del = updateById(touristInfo);

        if (updateOrderStatics <= 0 || !del){
            throw new BusinessException(SystemError.SYS_437);
        }

        QueryWrapper<SeriesOrderTouristInfo> queryWrapper4 = new QueryWrapper<>();
        queryWrapper4.lambda().eq(SeriesOrderTouristInfo::getOrderId, req.getOrderId());
        queryWrapper4.lambda().eq(SeriesOrderTouristInfo::getIsDeleted, IsDeletedCode.NO.getCode());
        List<SeriesOrderTouristInfo> dbTouristInfoList = seriesOrderTouristInfoMapper.selectList(queryWrapper4);

        boolean isDeleteAll = true;
        for (SeriesOrderTouristInfo dbTouristInfo : dbTouristInfoList) {
            if (!Objects.equals(dbTouristInfo.getIsDeleted(), IsDeletedCode.YES.getCode())) {
                isDeleteAll = false;
                break;
            }
        }
        if (isDeleteAll && statistics.getTotalPaidIn().compareTo(new BigDecimal(0)) <= 0) {
            SeriesOrder updateObject = EntityUtil.copy(req, SeriesOrder.class);
            updateObject.setIsDeleted(IsDeletedCode.YES.getCode());
            int delOrder = seriesOrderMapper.updateById(updateObject);
            if (delOrder <= 0){
                throw new BusinessException(SystemError.SYS_437);
            }
        }

        return Result.success(touristInfo.getId());
    }


    /**
     * 旅客名单
     */
    @Override
    public PageResponse<SeriesOrderTouristNameListDTO> nameList(SeriesOrderTouristNameListReq touristNameListReq) {
        Page<SeriesOrderTouristNameListDTO> iPage = new Page<>(touristNameListReq.getPageNo(), touristNameListReq.getPageSize());
        IPage<SeriesOrderTouristNameListDTO> touristPage = seriesOrderTouristInfoMapper.queryTouristList(iPage,touristNameListReq);

        if (CollectionUtils.isEmpty(touristPage.getRecords())) {
            return PageResponse.empty(touristPage.getCurrent());
        }

        List<SeriesOrderTouristNameListDTO> listDTOS = new ArrayList<>();
        SeriesOrderTouristNameListDTO nameListDTO ;
        for (SeriesOrderTouristNameListDTO record : touristPage.getRecords()) {
            nameListDTO = new SeriesOrderTouristNameListDTO();
            BeanUtils.copyProperties(record,nameListDTO);
            listDTOS.add(nameListDTO);
        }
        return new PageResponse<>(listDTOS, touristPage.getCurrent() == 1
                , touristPage.getTotal() <= (touristPage.getCurrent() * touristPage.getSize())
                , touristPage.getTotal(), touristPage.getCurrent(), touristPage.getSize());
    }

    /**
     * 旅客分组列表
     */
    @Override
    public PageResponse<SeriesOrderTouristRoomGroupDTO> queryList(SeriesOrderTouristRoomReq roomReq) {
        Page<SeriesOrderTouristRoomGroupDTO> iPage = new Page<>(roomReq.getPageNo(), roomReq.getPageSize());
        IPage<SeriesOrderTouristRoomGroupDTO> groupPage = seriesOrderTouristRoomMapper.queryList(iPage,roomReq);
        if(CollectionUtils.isEmpty(groupPage.getRecords())){
            return PageResponse.empty(groupPage.getCurrent());
        }
        List<SeriesOrderTouristRoomGroupDTO> dtoList = new ArrayList<>();
        SeriesOrderTouristRoomGroupDTO roomGroupDTO;
        for (SeriesOrderTouristRoomGroupDTO record : groupPage.getRecords()) {
            roomGroupDTO = new SeriesOrderTouristRoomGroupDTO();
            BeanUtils.copyProperties(record,roomGroupDTO);
            dtoList.add(roomGroupDTO);
        }
        return new PageResponse<>(dtoList, groupPage.getCurrent() == 1
                , groupPage.getTotal() <= (groupPage.getCurrent() * groupPage.getSize())
                , groupPage.getTotal(), groupPage.getCurrent(), groupPage.getSize());
    }

    /**
     * noShow
     */
    @Override
    public Result noShow(SeriesOrderTouristNoShowReq req) {
        if(CollectionUtils.isNotEmpty(req.getIds())){
            for (Long id : req.getIds()) {
                QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper();
                queryWrapper.eq("id",id);
                SeriesOrderTouristInfo touristInfo = new SeriesOrderTouristInfo();
                touristInfo.setNoshow(req.getNoShow());
                seriesOrderTouristInfoMapper.update(touristInfo,queryWrapper);
            }
        }
        return Result.success();
    }

    /**
     * lockStatus
     */
    @Override
    public Result lockStatus(SeriesOrderTouristNoShowReq req) {
        if(CollectionUtils.isNotEmpty(req.getIds())){
            for (Long id : req.getIds()) {
                QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper();
                queryWrapper.eq("id",id);
                SeriesOrderTouristInfo touristInfo = new SeriesOrderTouristInfo();
                touristInfo.setLockStatus(req.getLockStatus());
                seriesOrderTouristInfoMapper.update(touristInfo,queryWrapper);
            }
        }
        return Result.success();
    }

    /**
     * 游客分组
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result group(SeriesRoomGroupReq roomGroupReq) {
        if("2".equalsIgnoreCase(roomGroupReq.getType())){
            // 1. 自动分组,根据团期id
            QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("schedule_id",roomGroupReq.getScheduleId());
            queryWrapper.eq("is_deleted",0);
            List<SeriesOrderTouristInfo> infos = seriesOrderTouristInfoMapper.selectList(queryWrapper);
            List<SeriesOrderTouristInfo> dtos = new ArrayList<>(infos.size());
            Map<Long, SeriesOrderTouristGroup> map = new HashMap<>();
            SeriesOrderTouristGroup groupDto;
            // 查询最大组名  groupName
            SeriesOrderTouristGroup maxGroup = seriesOrderTouristGroupMapper.queryMaxGroupName();
            long groupNum = 1;
            if(null != maxGroup){
                String groupName = maxGroup.getGroupName();
                groupNum = StringUtils.isBlank(groupName) ? 1 : Long.valueOf(groupName) + 1;
            }
            Integer que = roomGroupReq.getQue();
            int a = 1;
            if(0 == infos.size()%que){
                long groupId = SnowflakeIdWorker.nextId();
                for (int i = 0; i < infos.size(); i++) {
                    SeriesOrderTouristInfo dto = infos.get(i);
                    dto.setGroupId(groupId);
                    dtos.add(dto);
                    groupDto = new SeriesOrderTouristGroup();
                    groupDto.setId(groupId);
                    groupDto.setGroupName(String.valueOf(groupNum));
                    groupDto.setOrderId(infos.get(i).getOrderId());
                    groupDto.setScheduleId(infos.get(i).getScheduleId());
                    groupDto.setCreateId(roomGroupReq.getUserId());
                    map.put(groupId,groupDto);
                    if(que == a){
                        a = 0;
                        groupId++;
                        groupNum++;
                    }
                    a++;
                }
            } else{
                // 余数不等0
                long groupId = SnowflakeIdWorker.nextId();
                long did = groupId;
                long eid = groupId;
                int c= infos.size() % que;
                for (int i = 0; i < infos.size()-c; i++) {
                    SeriesOrderTouristInfo dto = infos.get(i);
                    dto.setGroupId(did);
                    dtos.add(dto);
                    groupDto = new SeriesOrderTouristGroup();
                    groupDto.setId(groupId);
                    groupDto.setGroupName(String.valueOf(groupNum));
                    groupDto.setOrderId(infos.get(i).getOrderId());
                    groupDto.setScheduleId(infos.get(i).getScheduleId());
                    groupDto.setCreateId(roomGroupReq.getUserId());
                    map.put(groupId,groupDto);
                    if(que == a){
                        a = 0;
                        did++;
                    }
                    a++;
                }
                int e = infos.size()-c;
                for (int i = e; i < infos.size(); i++) {
                    SeriesOrderTouristInfo dto = infos.get(e);
                    dto.setGroupId(eid);
                    dtos.add(dto);
                    groupDto = new SeriesOrderTouristGroup();
                    groupDto.setId(groupId);
                    groupDto.setGroupName(String.valueOf(groupNum));
                    groupDto.setOrderId(infos.get(i).getOrderId());
                    groupDto.setScheduleId(infos.get(i).getScheduleId());
                    groupDto.setCreateId(roomGroupReq.getUserId());
                    map.put(groupId,groupDto);
                }
            }
            List<SeriesOrderTouristGroup> list = new ArrayList<>(map.values());
            // 根据dtos更新游客表
            for (SeriesOrderTouristInfo dto : dtos) {
                QueryWrapper<SeriesOrderTouristInfo> infoQueryWrapper = new QueryWrapper<>();
                infoQueryWrapper.eq("id",dto.getId());
                SeriesOrderTouristInfo info = new SeriesOrderTouristInfo();
                info.setModifiedId(roomGroupReq.getUserId());
                info.setGroupId(dto.getGroupId());
                seriesOrderTouristInfoMapper.update(info,infoQueryWrapper);
            }
            // 根据list 新增小组表
            for (SeriesOrderTouristGroup group : list) {
                seriesOrderTouristGroupMapper.insert(group);
            }
            //手动分组
        } else if("1".equalsIgnoreCase(roomGroupReq.getType())){
            List<Long> ids = roomGroupReq.getIds();
            if(CollectionUtils.isEmpty(roomGroupReq.getIds()) || org.springframework.util.StringUtils.isEmpty(roomGroupReq.getGroupId())){
                throw new BusinessException(SystemError.SYS_402);
            }
            seriesOrderTouristInfoMapper.batchUpdateGroupId(roomGroupReq.getGroupId(),roomGroupReq.getIds());
        }
        return Result.success();
    }


    /**
     * 游客分房
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result updateRoom(SeriesRoomRoomReq roomReq,Long userId) {
        SeriesOrderTouristRoom maxRoom = seriesOrderTouristRoomMapper.queryMaxRoom();
        int roomNum = 1;
        if(null != maxRoom){
            String roomNumber = maxRoom.getRoomNumber();
            roomNum = StringUtils.isBlank(roomNumber) ? 1 : Integer.valueOf(roomNumber) + 1;
        }
        if ("1".equalsIgnoreCase(roomReq.getRoomType())) {
            // 分房
            long roomId = SnowflakeIdWorker.nextId();
            List<Long> ids = roomReq.getIds();
            SeriesOrderTouristInfo seriesOrderTouristInfo = seriesOrderTouristInfoMapper.selectById(ids.get(0));
            if(null != seriesOrderTouristInfo){
                SeriesOrderTouristRoom room = new SeriesOrderTouristRoom();
                room.setId(roomId);
                room.setRoomNumber(String.valueOf(roomNum));
                room.setOrderId(seriesOrderTouristInfo.getOrderId());
                room.setScheduleId(seriesOrderTouristInfo.getScheduleId());
                room.setCreateId(userId);
                seriesOrderTouristRoomMapper.insert(room);
            }
            // 更新游客表
            for (Long id : ids) {
                QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper();
                queryWrapper.eq("id",id);
                SeriesOrderTouristInfo info = new SeriesOrderTouristInfo();
                info.setModifiedId(userId);
                info.setRoomId(roomId);
                info.setGmtModified(LocalDateTime.now());
                seriesOrderTouristInfoMapper.update(info,queryWrapper);
            }
        } else if ("2".equalsIgnoreCase(roomReq.getRoomType())) {
            // 取消分房 删除游客表中房号
            List<Long> ids = roomReq.getIds();
            if(CollectionUtils.isNotEmpty(ids)){
                for (Long id : ids) {
                    QueryWrapper<SeriesOrderTouristInfo> wrapper = new QueryWrapper<>();
                    wrapper.eq("id",id);
                    SeriesOrderTouristInfo info = new SeriesOrderTouristInfo();
                    info.setModifiedId(userId);
                    info.setGmtModified(LocalDateTime.now());
                    info.setRoomId(0L);
                    seriesOrderTouristInfoMapper.update(info,wrapper);
                }
            }
        }
        return Result.success();
    }


    /**
     * 查询所有游客分房
     */
    @Override
    public List<SeriesOrderTouristRoomDTO> roomList(SeriesOrderTouristRoomReq roomReq) {
        List<SeriesOrderTouristRoomDTO> dtos = seriesOrderTouristRoomMapper.roomList(roomReq);
        return dtos;
    }

    /**
     * 获取团信息
     * @param id
     * @return
     */
    @Override
    public SeriesGroupTouristInfoDTO groupInfo(Long id) {
        // 旅行团信息
        SeriesGroupTouristInfoDTO touristInfo = new SeriesGroupTouristInfoDTO();
        SeriesTripScheduleDTO scheduleDTO = iSeriesTripScheduleService.getTripScheduleId(id);
        if(null != scheduleDTO){
            touristInfo.setDepartureDate(scheduleDTO.getDepartureDate());
            touristInfo.setTripNumber(scheduleDTO.getTripNumber());
            touristInfo.setScheduleStatus(scheduleDTO.getScheduleStatus());
            // 余位数
            if(null != scheduleDTO.getSeriesTripScheduleTeamRuleDTO()){
                Integer maxPeople = scheduleDTO.getSeriesTripScheduleTeamRuleDTO().getMaxPeople();
                Integer lockedTouristNum = scheduleDTO.getSeriesTripScheduleDataDTO().getLockedTouristNum();
                if(null == scheduleDTO.getSeriesTripScheduleDataDTO()){
                    touristInfo.setTouristNum(maxPeople);
                }
                touristInfo.setTouristNum(maxPeople-lockedTouristNum);
            }
        }
        // 报名人数
        QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("schedule_id",id);
        queryWrapper.eq("is_deleted",0);
        List<SeriesOrderTouristInfo> infos = seriesOrderTouristInfoMapper.selectList(queryWrapper);
        // 报名类型人数
        touristInfo.setEnrollNum(infos.size());
        List<SeriesGroupTouristInfoDTO> infoDTOS = seriesOrderTouristInfoMapper.groupEnrollNum(id);
        if(CollectionUtils.isNotEmpty(infoDTOS)){
            for (int i = 0; i < infoDTOS.size(); i++) {
                if(i==0){
                    SeriesGroupTouristInfoDTO dto = infoDTOS.get(0);
                    touristInfo.setEnrollType1(dto.getPeopleType());
                    touristInfo.setEnrollTypeNum1(dto.getPeopleNum());
                }
                if(i==1){
                    SeriesGroupTouristInfoDTO dto = infoDTOS.get(1);
                    touristInfo.setEnrollType1(dto.getPeopleType());
                    touristInfo.setEnrollTypeNum1(dto.getPeopleNum());
                }
                if(i==2){
                    SeriesGroupTouristInfoDTO dto = infoDTOS.get(2);
                    touristInfo.setEnrollType1(dto.getPeopleType());
                    touristInfo.setEnrollTypeNum1(dto.getPeopleNum());
                }
            }
        }
        // 留位人数
        QueryWrapper<SeriesOrder> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("schedule_id",id);
        orderQueryWrapper.eq("is_deleted",0);
        orderQueryWrapper.eq("plus_tourist_type",2);
        List<SeriesOrder> orders = seriesOrderMapper.selectList(orderQueryWrapper);
        if(CollectionUtils.isNotEmpty(orders)){
            Integer people = 0;
            for (SeriesOrder order : orders) {
                Integer totalPeople = order.getTotalPeople();
                people += totalPeople;
            }
            touristInfo.setSurplusNum(people);
        }
        // 留位类型人数
        List<SeriesGroupTouristInfoDTO> dtos = seriesOrderTouristInfoMapper.groupSurplusNum(id);
        if(CollectionUtils.isNotEmpty(dtos)){
            for (int i = 0; i < dtos.size(); i++) {
                if(i==0){
                    SeriesGroupTouristInfoDTO dto = dtos.get(0);
                    touristInfo.setSurplusType1(dto.getPeopleType());
                    touristInfo.setSurplusTypeNum1(dto.getPeopleNum());
                }
                if(i==1){
                    SeriesGroupTouristInfoDTO dto = dtos.get(1);
                    touristInfo.setSurplusType2(dto.getPeopleType());
                    touristInfo.setSurplusTypeNum2(dto.getPeopleNum());
                }
                if(i==2){
                    SeriesGroupTouristInfoDTO dto = dtos.get(2);
                    touristInfo.setSurplusType3(dto.getPeopleType());
                    touristInfo.setSurplusTypeNum3(dto.getPeopleNum());
                }
            }
        }
        return touristInfo;
    }

    /**
     * 根据团期id查询组信息
     *
     * @param id 团期id
     * @return 组信息
     */
    @Override
    public Result<List<SeriesOrderTouristGroupDTO>> queryGroup(Long id) {
        QueryWrapper<SeriesOrderTouristGroup> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SeriesOrderTouristGroup::getScheduleId,id);
        queryWrapper.lambda().eq(SeriesOrderTouristGroup::getIsDeleted,0);
        List<SeriesOrderTouristGroup> groups = seriesOrderTouristGroupMapper.selectList(queryWrapper);
        if(CollectionUtils.isEmpty(groups)){
            return Result.failed(SystemError.SYS_411);
        }
        List<SeriesOrderTouristGroupDTO> groupDTOList = EntityUtil.copyList(groups, SeriesOrderTouristGroupDTO.class);
        return Result.success(groupDTOList);
    }

    /**
     * 新增游客分组
     *
     * @param scheduleId 团期id
     * @return 返回值
     */
    @Override
    public Result addGroup(Long scheduleId,Long userId) {
        try {
            QueryWrapper<SeriesOrderTouristGroup> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(SeriesOrderTouristGroup::getScheduleId,scheduleId);
            List<SeriesOrderTouristGroup> groups = seriesOrderTouristGroupMapper.selectList(queryWrapper);
            SeriesOrderTouristGroup group;
            if(CollectionUtils.isEmpty(groups)){
                group = new SeriesOrderTouristGroup();
                group.setId(SnowflakeIdWorker.nextId());
                group.setScheduleId(scheduleId);
                group.setGroupName("第1組");
                group.setCreateId(userId);
                group.setIsDeleted(0);
            } else {
                SeriesOrderTouristGroup touristGroup = groups.get(0);
                Long orderId = touristGroup.getOrderId();
                group = new SeriesOrderTouristGroup();
                group.setId(orderId);
                group.setScheduleId(scheduleId);
                group.setGroupName("第"+(groups.size()+1)+"組");
                group.setCreateId(userId);
                group.setIsDeleted(0);
            }
            int num = seriesOrderTouristGroupMapper.insert(group);
            if(num<1){
                throw new BusinessException(SystemError.SYS_437);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.success();
    }

    /**
     * 删除游客分组
     * @param groupId 分组id
     * @param userId 用户id
     * @return
     */
    @Override
    public Result deleteGroup(Long groupId,Long userId){
        try {
            QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(SeriesOrderTouristInfo::getGroupId,groupId).eq(SeriesOrderTouristInfo::getIsDeleted,IsDeletedCode.NO.getCode());
            Integer count = seriesOrderTouristInfoMapper.selectCount(queryWrapper);
            if(count > 0){
                return Result.failed(SystemError.TOUR_ORDER_30039);
            }
            SeriesOrderTouristGroup seriesOrderTouristGroup = new SeriesOrderTouristGroup();
            seriesOrderTouristGroup.setId(groupId);
            seriesOrderTouristGroup.setIsDeleted(IsDeletedCode.YES.getCode());
            seriesOrderTouristGroup.setModifiedId(userId);
            seriesOrderTouristGroup.setGmtModified(LocalDateTime.now());
            seriesOrderTouristGroupMapper.updateById(seriesOrderTouristGroup);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.success();
    }

    /**
     * 移除分组下的游客
     * @param req req
     * @param userId
     * @return 返回值
     */
    @Override
    public Result removeGroupTourist(RemoveGroupTouristReq req,Long userId){
        try {
            Long groupId = req.getGroupId();
            List<Long> ids = req.getIds();
            if(org.springframework.util.StringUtils.isEmpty(groupId) || CollectionUtils.isEmpty(ids)){
                return Result.failed(SystemError.SYS_402);
            }
            SeriesOrderTouristGroup seriesOrderTouristGroup = seriesOrderTouristGroupMapper.selectById(groupId);
            if(org.springframework.util.StringUtils.isEmpty(seriesOrderTouristGroup)){
                return Result.failed(SystemError.SYS_411);
            }
            seriesOrderTouristInfoMapper.batchUpdateGroupId(0L,ids);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.success();
    }

    @Override
    public Result<SeriesOrderTouristInfoDetailDTO> detail(SeriesOrderTouristInfoDetailReq req) {
        SeriesOrderTouristInfo touristInfo = getById(req.getId());
        SeriesOrderTouristInfoDetailDTO dto = EntityUtil.copy(touristInfo, SeriesOrderTouristInfoDetailDTO.class);
        List<SeriesOrderTouristInfoDetailCertificateDTO> certificateDTOList = new ArrayList<>();
        if (touristInfo.getCertificateType1() != null || touristInfo.getCertificateTypeId1() != null || touristInfo.getCertificateNumber1() != null
                || touristInfo.getCertificateValidDate1() != null || touristInfo.getCertificatePlace1() != null
                || touristInfo.getCertificatePlaceId1() != null) {
            SeriesOrderTouristInfoDetailCertificateDTO certificateDTO = new SeriesOrderTouristInfoDetailCertificateDTO();
            certificateDTO.setCertificateType(touristInfo.getCertificateType1());
            certificateDTO.setCertificateTypeId(touristInfo.getCertificateTypeId1());
            certificateDTO.setCertificateNumber(touristInfo.getCertificateNumber1());
            certificateDTO.setCertificateValidDate(touristInfo.getCertificateValidDate1());
            certificateDTO.setCertificatePlace(touristInfo.getCertificatePlace1());
            certificateDTO.setCertificatePlaceId(touristInfo.getCertificatePlaceId1());
            certificateDTOList.add(certificateDTO);
        }
        if (touristInfo.getCertificateType2() != null || touristInfo.getCertificateTypeId2() != null || touristInfo.getCertificateNumber2() != null
                || touristInfo.getCertificateValidDate2() != null || touristInfo.getCertificatePlace2() != null
                || touristInfo.getCertificatePlaceId2() != null) {
            SeriesOrderTouristInfoDetailCertificateDTO certificateDTO = new SeriesOrderTouristInfoDetailCertificateDTO();
            certificateDTO.setCertificateType(touristInfo.getCertificateType2());
            certificateDTO.setCertificateTypeId(touristInfo.getCertificateTypeId2());
            certificateDTO.setCertificateNumber(touristInfo.getCertificateNumber2());
            certificateDTO.setCertificateValidDate(touristInfo.getCertificateValidDate2());
            certificateDTO.setCertificatePlace(touristInfo.getCertificatePlace2());
            certificateDTO.setCertificatePlaceId(touristInfo.getCertificatePlaceId2());
            certificateDTOList.add(certificateDTO);
        }
        if (touristInfo.getCertificateType3() != null || touristInfo.getCertificateTypeId3() != null || touristInfo.getCertificateNumber3() != null
                || touristInfo.getCertificateValidDate3() != null || touristInfo.getCertificatePlace3() != null
                || touristInfo.getCertificatePlaceId3() != null) {
            SeriesOrderTouristInfoDetailCertificateDTO certificateDTO = new SeriesOrderTouristInfoDetailCertificateDTO();
            certificateDTO.setCertificateType(touristInfo.getCertificateType3());
            certificateDTO.setCertificateTypeId(touristInfo.getCertificateTypeId3());
            certificateDTO.setCertificateNumber(touristInfo.getCertificateNumber3());
            certificateDTO.setCertificateValidDate(touristInfo.getCertificateValidDate3());
            certificateDTO.setCertificatePlace(touristInfo.getCertificatePlace3());
            certificateDTO.setCertificatePlaceId(touristInfo.getCertificatePlaceId3());
            certificateDTOList.add(certificateDTO);
        }
        dto.setCertificateList(certificateDTOList);
        return Result.success(dto);
    }

    /**
     * 预览发票
     */
    @Override
    public Result<CustomOrderTouristInfoPreviewInvoiceDTO> previewInvoice(SeriesOrderTouristInfoPreviewInvoiceReq req, TokenUser currentUser) {
        SeriesOrder order = seriesOrderMapper.selectById(req.getOrderId());
        if (order == null || Objects.equals(order.getIsDeleted(),1)){
            throw new BusinessException(SystemError.CUSTOM_ORDER_4008);
        }
        if (req.getTouristIdList().size() <= 0) {
            return Result.failed(SystemError.SYS_409);
        }
        Long firstTouristId = req.getTouristIdList().get(0);
        SeriesOrderTouristInfo firstTouristInfo = seriesOrderTouristInfoMapper.selectById(firstTouristId);
        if (firstTouristInfo == null  || Objects.equals(firstTouristInfo.getIsDeleted(), NumberConstant.ONE.getValue())) {
            return Result.failed(SystemError.SYS_411);
        }
        CustomOrderTouristInfoPreviewInvoiceDTO dto = new CustomOrderTouristInfoPreviewInvoiceDTO();
        dto.setEnquiryNo(CharUtil.getRandomStr(6));
        dto.setTripName(order.getTripTitle());

        //團體/旅客姓名/To
        dto.setCnSurname(firstTouristInfo.getCnSurname());
        dto.setCnName(firstTouristInfo.getCnName());
        dto.setEnSurname(firstTouristInfo.getEnSurname());
        dto.setEnName(firstTouristInfo.getEnName());

        //订单联系人
        dto.setContactCnSurname(order.getContactCnSurname());
        dto.setContactCnName(order.getContactCnName());
        dto.setContactEnSurname(order.getContactEnSurname());
        dto.setContactEnName(order.getContactEnName());
        dto.setContactEmail(order.getContactEmail());
        dto.setContactPhone(order.getContactTelephones());
        /*if (StringUtils.isNotBlank(order.getContactTelephones())) {
            List<ContactTelephoneJson> telephoneJsonList = JSON.parseArray(order.getContactTelephones(), ContactTelephoneJson.class);
            ContactTelephoneJson telephoneJson = telephoneJsonList.get(0);
            dto.setContactAreaCode(telephoneJson.getContactTelAreaCode());
            dto.setContactPhone(telephoneJson.getContactTelephones());
        }*/
        //销售人员
        UserDTO createUser = iSysUserService.queryCacheUser(order.getCreateId());
        if (createUser != null) {
            //應付日期/Due Date：門市編號+員工編號+月日4位+時分秒6位
            dto.setInvoiceNumber(createUser.getDeptCode()+createUser.getEmployeeNumber()+DateUtil.fmt(LocalDateTime.now(),"MMddHHmmss"));
            dto.setOrderUsername(createUser.getUsername());
            dto.setOrderAreaCode(createUser.getMobileAreaCode());
            dto.setOrderPhone(createUser.getMobile());
        }
        //当前用户
        dto.setCurrentUsername(currentUser.getUsername());
        dto.setCurrentDate(LocalDate.now());
        //摘要
        List<TouristCollectionFeeInfoDTO> touristCollectionFeeInfoList = new ArrayList<>();
        //总金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        for (Long id : req.getTouristIdList()) {
            SeriesOrderTouristInfo touristInfo = seriesOrderTouristInfoMapper.selectById(id);
            //摘要
            TouristCollectionFeeInfoDTO collectionFeeInfoDTO = new TouristCollectionFeeInfoDTO();
            collectionFeeInfoDTO.setCnName(touristInfo.getCnFullname());
            collectionFeeInfoDTO.setEnName(touristInfo.getEnFullname());
            collectionFeeInfoDTO.setTouristTotalAmount(touristInfo.getTotalReceivables());
            totalAmount = totalAmount.add(touristInfo.getTotalReceivables());
            List<TouristCollectionFeeJson> groupFeeList = new ArrayList<>();
            //团费
            TouristCollectionFeeJson groupFee = new TouristCollectionFeeJson();
            groupFee.setProjectName("團費");
            groupFee.setTotalAmount(touristInfo.getGroupFee());
            groupFee.setAdjustType(1);
            groupFeeList.add(groupFee);
            collectionFeeInfoDTO.setGroupFee(groupFeeList);
            if (StringUtils.isNotBlank(touristInfo.getCollectionFeeJson())){
                //代收费用
                List<TouristCollectionFeeJson> collectionFeeList = JSON.parseArray(touristInfo.getCollectionFeeJson(), TouristCollectionFeeJson.class);
                if (CollectionUtils.isNotEmpty(collectionFeeList)){
                    collectionFeeList.forEach(collectionFeeJson -> {
                        collectionFeeJson.setAdjustType(1);
                    });
                    collectionFeeInfoDTO.setCollectionFee(collectionFeeList);
                }
            }
            //调整费用
            List<TouristCollectionFeeJson> adjustFeeList = seriesOrderTouristFeeAdjustMapper.queryByTourist(touristInfo.getId());
            if (CollectionUtils.isNotEmpty(adjustFeeList)){
                collectionFeeInfoDTO.setAdjustFee(adjustFeeList);
            }
            //其他费用
            List<TouristCollectionFeeJson> otherFeeList = seriesOrderTouristOtherFeeMapper.selectByTourist(touristInfo.getId());
            if (CollectionUtils.isNotEmpty(otherFeeList)){
                collectionFeeInfoDTO.setOtherFee(otherFeeList);
            }
            collectionFeeInfoDTO.setIsWillExpire(0);
            //证件是否快到期
            if (touristInfo.getCertificateValidDate1() != null){
                int toDays = (int) Duration.between(LocalDateTime.now(), DateUtil.parse(DateUtil.fmtLocalDate(touristInfo.getCertificateValidDate1(),"yyyy-MM-dd"))).toDays();
                if (toDays <= 72){
                    collectionFeeInfoDTO.setIsWillExpire(1);
                }
            }
            if (touristInfo.getCertificateValidDate2() != null){
                int toDays = (int)Duration.between(LocalDateTime.now(), DateUtil.parse(DateUtil.fmtLocalDate(touristInfo.getCertificateValidDate2(),"yyyy-MM-dd"))).toDays();
                if (toDays <= 72){
                    collectionFeeInfoDTO.setIsWillExpire(1);
                }
            }
            if (touristInfo.getCertificateValidDate3() != null){
                int toDays = (int)Duration.between(LocalDateTime.now(), DateUtil.parse(DateUtil.fmtLocalDate(touristInfo.getCertificateValidDate3(),"yyyy-MM-dd"))).toDays();
                if (toDays <= 72){
                    collectionFeeInfoDTO.setIsWillExpire(1);
                }
            }
            touristCollectionFeeInfoList.add(collectionFeeInfoDTO);
        }
        dto.setTouristCollectionFeeInfoList(touristCollectionFeeInfoList);
        dto.setTotalAmount(totalAmount);
        return Result.success(dto);
    }

    /**
     * 增加某旅客的调整费用
     * @param touristId
     * @param amount 增加的金额，可为负
     */
    @Transactional
    @Override
    public void addTouristAdjustmentAmount(Long touristId, BigDecimal amount, Long userId) {
    	validateNotNull(touristId, amount);
    	
    	if (amount == null) 
    		return;
    	
    	SeriesOrderTouristInfo entity = seriesOrderTouristInfoMapper.assertExistById(touristId);
    	entity.setTotalReceivables(Assist.add(amount, entity.getTotalReceivables()));
    	entity.setRemainingReceivables(Assist.subtract(entity.getTotalReceivables(), entity.getTotalPaidIn()));
    	entity.setAdjustmentCost(Assist.add(amount, entity.getAdjustmentCost()));    	
    	entity.setGmtModified(LocalDateTime.now());
    	entity.setModifiedId(userId);
    	getBaseMapper().updateById(entity);
    }

    /**
     * 获取房间数范围
     *
     * @param req
     * @return
     */
    @Override
    public Result<SingleRoomCalculateDTO> calculate(SingleRoomCalculateReq req) {
        //获取团期
        SeriesTripScheduleDTO tripScheduleDTO = iSeriesTripScheduleService.getTripScheduleId(req.getScheduleId());
        if (tripScheduleDTO == null){
            return Result.failed(new BusinessException(SystemError.TOUR_30012));
        }
        //校验旅客类型人数是否合理
        //成人+长者 人数
        int man = 0;
        //小童+婴儿 人数
        int kid = 0;
        for (SeriesOrderTouristReq req1 : req.getTouristList()) {
            if (Objects.equals(req1.getTouristTypeId(), TouristType.ADULT.getId()) || Objects.equals(req1.getTouristTypeId(), TouristType.ELDER.getId())){
                man += req1.getPeople();
            }else if (Objects.equals(req1.getTouristTypeId(), TouristType.BABY.getId()) || Objects.equals(req1.getTouristTypeId(), TouristType.CHILD.getId())){
                kid += req1.getPeople();
            }
        }
        if (kid > (man * 2)){
            return Result.failed(new BusinessException(SystemError.TOUR_ORDER_30020,kid,man));
        }
        SeriesTripScheduleTeamRuleDTO seriesTripScheduleTeamRuleDTO = tripScheduleDTO.getSeriesTripScheduleTeamRuleDTO();
        //占床数
        int occupyBedNum = 0;
        //不占床数
        int notOccupyBedNum = 0;
        //最大房间数
        int maxRooms = 0;
        for (SeriesOrderTouristReq touristReq : req.getTouristList()) {
            //单房差
            for (Passenger passenger : seriesTripScheduleTeamRuleDTO.getPassenger()) {
                if (Objects.equals(passenger.getMainDataId(), touristReq.getTouristTypeId())) {
                    if (Objects.equals(passenger.getIsOccupyBed(), IsOccupyBedCode.YES.getCode())) {
                        maxRooms += touristReq.getPeople();
                        occupyBedNum += touristReq.getPeople();
                    } else if (Objects.equals(passenger.getIsOccupyBed(), IsOccupyBedCode.NO.getCode())) {
                        notOccupyBedNum += touristReq.getPeople();
                    }
                }
            }
        }
        //计算最终所需房间数
        Map<String, Integer> roomsResult = SingleRoomUtil.computeRooms(occupyBedNum, notOccupyBedNum,
                0,
                (double) seriesTripScheduleTeamRuleDTO.getOccupyBedNum(),
                (double) seriesTripScheduleTeamRuleDTO.getNotOccupyBedNum());
    //    Integer singleRoomNum = roomsResult.get("singleRoomNum");
        Integer rooms = roomsResult.get("rooms");
        SingleRoomCalculateDTO dto = new SingleRoomCalculateDTO();
        dto.setMinRooms(rooms);
        dto.setMaxRooms(maxRooms);
        List<RoomDTO> list = new ArrayList<>();
        for (int i=rooms;i<=maxRooms;i++){
            RoomDTO roomDTO = new RoomDTO();
            roomDTO.setText(i+"");
            roomDTO.setValue(i);
            list.add(roomDTO);
        }
        dto.setList(list);
        return Result.success(dto);
    }

    /**
     * 校验旅客类型人数是否合理
     * @param touristList
     * @return
     */
    private boolean checkTouristNumber(List<SeriesOrderTouristReq> touristList) {
        //成人+长者 人数
        int man = 0;
        //小童+婴儿 人数
        int kid = 0;
        for (SeriesOrderTouristReq req : touristList) {
            if (Objects.equals(req.getTouristTypeId(), TouristType.ADULT.getId()) || Objects.equals(req.getTouristTypeId(), TouristType.ELDER.getId())){
                man += req.getPeople();
            }else if (Objects.equals(req.getTouristTypeId(), TouristType.BABY.getId()) || Objects.equals(req.getTouristTypeId(), TouristType.CHILD.getId())){
                kid += req.getPeople();
            }
        }
        if ((kid * 2) > man){
            throw new BusinessException(SystemError.TOUR_ORDER_30020);
        }
        return true;
    }

    /**
     * 统计已下单人数(内部接口)
     *
     * @param scheduleDTOList
     * @return
     */
    @Override
    public List<ScheduleOrderPeopleDTO> sumOrderPeople(List<ScheduleOrderPeopleDTO> scheduleDTOList) {
        scheduleDTOList.forEach(schedule -> {
            Long total = seriesOrderTouristInfoMapper.sumBySchedule(schedule.getId());
            schedule.setOrderPeople(total==null?0:total.intValue());
        });
        return scheduleDTOList;
    }

    /**
     * 获取国籍ID
     *
     * @param nation
     * @return
     */
    @Override
    public Long getNationId(String nation) {
        if (StringUtils.isNotBlank(nation)){
            List<AreaDTO> areaDTOS = iSysAreaService.esOneLevel(nation);
            if (CollectionUtils.isNotEmpty(areaDTOS)){
                return areaDTOS.get(0).getId();
            }
        }
        return null;
    }

    /**
     * 获取证件类型ID
     *
     * @param stringCellValue
     * @return
     */
    @Override
    public Long getCertificateTypeId(String stringCellValue) {
        List<MainDataRowFieldDataDTO> list = iMainDataTableService.groupByDataField(1348475429155237889L,1348477526361763842L);
        for (MainDataRowFieldDataDTO item : list) {
            if (stringCellValue.equals(item.getFieldValue())){
                return item.getId();
            }
        }
        return null;
    }

    /**
     * 导入旅客名单
     *
     * @param tempList
     * @param userId
     * @param orderId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result exportIn(List<ExcelTemp> tempList, Long userId, Long orderId) {
        if (CollectionUtils.isEmpty(tempList)){
            throw new BusinessException(SystemError.FINANCE_ERROR_17036);
        }
        SeriesOrder order = seriesOrderMapper.selectById(orderId);
        SeriesTripScheduleDTO tripScheduleDTO = iSeriesTripScheduleService.getTripScheduleId(order.getScheduleId());
        List<SeriesOrderTouristInfo> list = new ArrayList<>();
        for (ExcelTemp temp : tempList) {
            SeriesOrderTouristInfo touristInfo = EntityUtil.copy(temp,SeriesOrderTouristInfo.class);
            int age = touristInfo.getBirthday().until(LocalDate.now()).getYears();
            //判断年龄
            List<Passenger> passengers = tripScheduleDTO.getSeriesTripScheduleTeamRuleDTO().getPassenger();
            for (Passenger passenger : passengers){
                if (Objects.equals(passenger.getMainDataId(),touristInfo.getMainDataId())){
                    if (age >= passenger.getAgeBegin() && age < passenger.getAgeEnd()){
                        break;
                    }else{
                        throw new BusinessException(SystemError.CUSTOM_ORDER_4004);
                    }
                }
            }

            touristInfo.setModifiedId(userId);
            touristInfo.setIsFullInfo(1);
            list.add(touristInfo);
        }
        boolean batch = updateBatchById(list);
        if (!batch){
            throw new BusinessException(SystemError.SYS_411);
        }
        return Result.success();
    }

    /**
     * 导出旅客模板
     *
     * @param req
     * @return
     */
    @Override
    public ExcelData exportOut(CustomOrderIdReq req) {
        //旅客列表
        QueryWrapper<SeriesOrderTouristInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id",req.getId());
        queryWrapper.eq("is_deleted",0);
        List<SeriesOrderTouristInfo> touristInfoList = seriesOrderTouristInfoMapper.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(touristInfoList)){
            ExcelData data = new ExcelData();
            data.setName(req.getId().toString());
            List<List<String>> title = new ArrayList();
            //设置Excel表头
            List<String> remark = setExcelHeaderRemark();
            List<String> header = setExcelHeader();
            //设置数据
            List<List<Object>> rows = new ArrayList();
            for (SeriesOrderTouristInfo touristInfo : touristInfoList) {
                //筛选过滤
                List<Object> row = setRow(touristInfo);
                rows.add(row);
            }
            if (rows.size() == 0){
                throw new BusinessException(SystemError.FINANCE_BILL_17023);
            }

            title.add(remark);
            title.add(header);
        //    data.setRemark(remark);
            data.setTitles(title);
            data.setRows(rows);

            return data;
        }
        return null;
    }

    /**
     * 设置数据
     * @param touristInfo
     * @return
     */
    private List<Object> setRow(SeriesOrderTouristInfo touristInfo) {
        List<Object> row = new ArrayList();
        row.add(touristInfo.getId());
        row.add(touristInfo.getTouristTypeName());
        row.add(touristInfo.getCnSurname());
        row.add(touristInfo.getCnName());
        row.add(touristInfo.getEnSurname());
        row.add(touristInfo.getEnName());
        String gender = getGender(touristInfo.getGender());
        row.add(gender);
        row.add(touristInfo.getMobileAreaCode());
        row.add(touristInfo.getMobile());
        if (touristInfo.getBirthday() != null){
            row.add(DateUtil.fmtLocalDate(touristInfo.getBirthday(),"yyyyMMdd"));
        }else{
            row.add("");
        }
        row.add(touristInfo.getNation());
        row.add(touristInfo.getEmail());
        row.add(touristInfo.getRemark());
        row.add(touristInfo.getCertificateType1());
        row.add(touristInfo.getCertificateNumber1());
        if (touristInfo.getCertificateValidDate1() != null){
            row.add(DateUtil.fmtLocalDate(touristInfo.getCertificateValidDate1(),"yyyyMMdd"));
        }else{
            row.add("");
        }
        row.add(touristInfo.getCertificatePlace1());
        row.add(touristInfo.getCertificateType2());
        row.add(touristInfo.getCertificateNumber2());
        if (touristInfo.getCertificateValidDate2() != null){
            row.add(DateUtil.fmtLocalDate(touristInfo.getCertificateValidDate2(),"yyyyMMdd"));
        }else{
            row.add("");
        }
        row.add(touristInfo.getCertificatePlace2());
        row.add(touristInfo.getCertificateType3());
        row.add(touristInfo.getCertificateNumber3());
        if (touristInfo.getCertificateValidDate3() != null){
            row.add(DateUtil.fmtLocalDate(touristInfo.getCertificateValidDate3(),"yyyyMMdd"));
        }else{
            row.add("");
        }
        row.add(touristInfo.getCertificatePlace3());
        row.add(touristInfo.getEmergencyContactName());
        row.add(touristInfo.getEmergencyMobileAreaCode());
        row.add(touristInfo.getEmergencyMobile());
        return row;
    }

    /**
     * 获取称谓
     * @param gender
     * @return
     */
    private String getGender(Integer gender) {
        if (gender != null){
           if (Objects.equals(gender,1)){
               return "先生";
           }else if (Objects.equals(gender,2)){
               return "女士";
           }else if (Objects.equals(gender,3)){
               return "小姐";
           }else if (Objects.equals(gender,4)){
               return "男童";
           }else if (Objects.equals(gender,5)){
               return "女童";
           }
        }
        return null;
    }

    /**
     * 设置表头注释
     * @return
     */
    private List<String> setExcelHeaderRemark() {
        List<String> header = new ArrayList();
        header.add("此字段不要修改");
        header.add("此字段不要修改");
        header.add("");
        header.add("");
        header.add("");
        header.add("");
        header.add("請輸入“先生/女生/小姐/男童/女童”");
        header.add("例如：+852");
        header.add("");
        header.add("格式：19980101");
        header.add("");
        header.add("");
        header.add("");
        header.add("");
        header.add("");
        header.add("格式：19980101");
        header.add("");
        header.add("");
        header.add("");
        header.add("格式：19980101");
        header.add("");
        header.add("");
        header.add("");
        header.add("格式：19980101");
        header.add("");
        header.add("");
        header.add("例如：+852");
        header.add("");
        return header;
    }

    /**
     * 设置表头
     * @return
     */
    private List<String> setExcelHeader() {
        List<String> header = new ArrayList();
        header.add("ID");
        header.add("*旅客類型");
        header.add("*中文姓");
        header.add("*中文名");
        header.add("*英文姓");
        header.add("*英文名");
        header.add("*稱謂");
        header.add("*手機區號");
        header.add("*電話號碼");
        header.add("*出生日期");
        header.add("國籍");
        header.add("Email");
        header.add("備註");
        header.add("證件類型1");
        header.add("證件號碼1");
        header.add("證件有效期1");
        header.add("證件簽發地1");
        header.add("證件類型2");
        header.add("證件號碼2");
        header.add("證件有效期2");
        header.add("證件簽發地2");
        header.add("證件類型3");
        header.add("證件號碼3");
        header.add("證件有效期3");
        header.add("證件簽發地3");
        header.add("緊急聯絡人姓名");
        header.add("緊急聯絡手機區號");
        header.add("紧急聯絡電話號碼");
        return header;
    }

}
